1.1 --- a/micropython/code.py Mon Feb 06 19:06:46 2012 +0100
1.2 +++ b/micropython/code.py Sun Feb 26 19:36:56 2012 +0100
1.3 @@ -230,7 +230,7 @@
1.4
1.5 "Reset the target of the active instruction to 'target'."
1.6
1.7 - self.optimiser.set_target(target)
1.8 + self.optimiser.set_target("working", target)
1.9
1.10 def is_immediate_user(self, node):
1.11
1.12 @@ -264,7 +264,7 @@
1.13 """
1.14
1.15 temp = LoadTemp(None)
1.16 - self.optimiser.request_active_value(temp, self.blocks[-1], len(self.blocks[-1].code))
1.17 + self.optimiser.request_active_value("working", temp, self.blocks[-1], len(self.blocks[-1].code))
1.18 return temp
1.19
1.20 def set_temp(self, temp, block, pos):
1.21 @@ -326,7 +326,7 @@
1.22 # Prevent any requested active value from generating instructions now
1.23 # that our interest in it has passed.
1.24
1.25 - self.optimiser.ignore_active_value()
1.26 + self.optimiser.ignore_active_value("working")
1.27
1.28 def free_temp(self, temp_position):
1.29
1.30 @@ -365,7 +365,7 @@
1.31
1.32 # Add the operation to the current block.
1.33
1.34 - self.optimiser.set_new(op)
1.35 + self.optimiser.set_new("working", op)
1.36 self.blocks[-1].append(op)
1.37 return 1
1.38
1.39 @@ -411,13 +411,14 @@
1.40 self.remove_op()
1.41 self.new_op(op)
1.42
1.43 - def replace_active_value(self, op):
1.44 + def replace_active_value(self, register, op):
1.45
1.46 """
1.47 - Replace the value-providing active instruction with 'op' if appropriate.
1.48 + Replace the active instruction providing 'register' with its value with
1.49 + the given 'op' if appropriate.
1.50 """
1.51
1.52 - removed = self.optimiser.remove_active_value()
1.53 + removed = self.optimiser.remove_active_value(register)
1.54 self.new_op(op)
1.55 return removed
1.56
2.1 --- a/micropython/opt.py Mon Feb 06 19:06:46 2012 +0100
2.2 +++ b/micropython/opt.py Sun Feb 26 19:36:56 2012 +0100
2.3 @@ -52,13 +52,17 @@
2.4 # control-flow operations will flush the "active" instruction.
2.5
2.6 self.active = None
2.7 - self.saved_value_op = None
2.8 - self.saved_value_block = None
2.9 - self.saved_value_pos = None
2.10 +
2.11 + # Information about instructions providing the active values for
2.12 + # registers.
2.13
2.14 - # Instructions providing the active value.
2.15 + self.saved_value_op = {}
2.16 + self.saved_value_block = {}
2.17 + self.saved_value_pos = {}
2.18
2.19 - self.active_values = set()
2.20 + # Sets of instructions providing the active value for each register.
2.21 +
2.22 + self.active_values = {}
2.23
2.24 def get_attribute_store_instructions(self):
2.25
2.26 @@ -86,13 +90,13 @@
2.27 collecting the active instructions from each of the blocks otherwise.
2.28 """
2.29
2.30 - self.store_active_value()
2.31 + self.store_active_values()
2.32 self.clear_active()
2.33
2.34 # Make a new collection of instructions for a new block.
2.35
2.36 if block:
2.37 - self.active_values = set()
2.38 + self.active_values = {}
2.39 block.set_active_values(self.active_values)
2.40
2.41 # Otherwise, clear the collection for an existing block.
2.42 @@ -104,51 +108,77 @@
2.43 for b in blocks:
2.44 self.active_values.update(b.get_active_values())
2.45
2.46 - def set_new(self, op):
2.47 + def set_new(self, register, op):
2.48
2.49 - "Set the latest 'op' as the active instruction."
2.50 + "For 'register', set the latest 'op' as the active instruction."
2.51
2.52 self.set_active(op)
2.53 - self.set_active_value(op)
2.54 + self.set_active_value(register, op)
2.55 +
2.56 + def set_active_value(self, register, op):
2.57 +
2.58 + "For 'register', set 'op' as the value-providing active instruction."
2.59
2.60 - def set_active_value(self, op):
2.61 + # Since the current value provider may eventually be used, it needs to
2.62 + # store its output if appropriate.
2.63
2.64 - "Set the value-providing active instruction."
2.65 + self.store_active_value(register)
2.66 + self.active_values[register] = set([op])
2.67
2.68 - if affects_register(op, "working"):
2.69 - self.store_active_value()
2.70 - self.active_values.clear()
2.71 - self.active_values.add(op)
2.72 + def get_active_value(self, register):
2.73
2.74 - def get_active_value(self):
2.75 + """
2.76 + Get any single active value for the given 'register' or None if none or
2.77 + more than one exist.
2.78 + """
2.79
2.80 - "Get any single active value or None if none or more than one exist."
2.81 + if self.active_values.has_key(register) and \
2.82 + len(self.active_values[register]) == 1:
2.83
2.84 - if len(self.active_values) == 1:
2.85 - return list(self.active_values)[0]
2.86 + return list(self.active_values[register])[0]
2.87 +
2.88 else:
2.89 return None
2.90
2.91 - def remove_active_value(self):
2.92 + def remove_active_value(self, register):
2.93
2.94 """
2.95 - Remove the value-providing active instruction from the generated code,
2.96 - if appropriate, but keep a record of the active instruction itself.
2.97 + Remove the active instruction providing 'register' with its value from
2.98 + the generated code, if appropriate, and return the active instruction.
2.99 """
2.100
2.101 - if self.active in self.active_values:
2.102 + if self.active_values.has_key(register) and \
2.103 + self.active in self.active_values[register]:
2.104 +
2.105 removed = self.translation.remove_op()
2.106 - self.active_values.remove(removed)
2.107 + self.active_values[register].remove(removed)
2.108 return removed
2.109 +
2.110 else:
2.111 return None
2.112
2.113 - def set_target(self, target):
2.114 + def set_target(self, register, target):
2.115 +
2.116 + """
2.117 + Set the target of the active instruction involving 'register' to
2.118 + 'target'.
2.119 + """
2.120 +
2.121 + if self.active_values.has_key(register):
2.122 + for expr in self.active_values[register]:
2.123 + expr.target = target
2.124
2.125 - "Set the target of the active instruction to 'target'."
2.126 + # Transfer the active instructions to their new target.
2.127
2.128 - for expr in self.active_values:
2.129 - expr.target = target
2.130 + if not self.active_values.has_key(target):
2.131 + self.active_values[target] = self.active_values[register]
2.132 + else:
2.133 + self.active_values[target].update(self.active_values[register])
2.134 +
2.135 + # Remove the association between the instructions and the specified
2.136 + # register.
2.137 +
2.138 + del self.active_values[register]
2.139
2.140 def set_active(self, op):
2.141
2.142 @@ -164,33 +194,57 @@
2.143
2.144 # Permit the active value to be requested and restored.
2.145
2.146 - def request_active_value(self, temp, block, pos):
2.147 + def request_active_value(self, register, temp, block, pos):
2.148
2.149 """
2.150 - Request the current active value so that if the value is changed, a
2.151 - temporary storage element or equivalent will be allocated.
2.152 + Request the current active value for 'register' so that if the value is
2.153 + changed, a temporary storage element or equivalent will be allocated.
2.154 """
2.155
2.156 - self.store_active_value()
2.157 - self.saved_value_op = temp
2.158 - self.saved_value_block = block
2.159 - self.saved_value_pos = pos
2.160 + # Cause any previously active value for the register to be saved.
2.161 +
2.162 + self.store_active_value(register)
2.163 +
2.164 + # Redefine the active value for the register.
2.165 +
2.166 + self.saved_value_op[register] = temp
2.167 + self.saved_value_block[register] = block
2.168 + self.saved_value_pos[register] = pos
2.169
2.170 - def store_active_value(self):
2.171 + def store_active_values(self):
2.172 +
2.173 + "Store all active values."
2.174
2.175 - "Store the requested active value"
2.176 + for register in self.active_values.keys():
2.177 + self.store_active_value(register)
2.178 +
2.179 + def store_active_value(self, register):
2.180 +
2.181 + "Store the requested active value for 'register'."
2.182
2.183 - if self.saved_value_op is not None:
2.184 - self.translation.set_temp(self.saved_value_op, self.saved_value_block, self.saved_value_pos)
2.185 - self.ignore_active_value()
2.186 + if self.saved_value_op.has_key(register):
2.187 +
2.188 + # Cause an instruction to be inserted to store the active value for
2.189 + # the register, thus keeping it available for any subsequent usage.
2.190
2.191 - def ignore_active_value(self):
2.192 + self.translation.set_temp(
2.193 + self.saved_value_op[register], # cause the storage of the value
2.194 + self.saved_value_block[register], # in the appropriate block
2.195 + self.saved_value_pos[register] # at the appropriate location
2.196 + )
2.197
2.198 - "Ignore the active value."
2.199 + # Discard the existing active value information.
2.200 +
2.201 + self.ignore_active_value(register)
2.202 +
2.203 + def ignore_active_value(self, register):
2.204
2.205 - self.saved_value_op = None
2.206 - self.saved_value_block = None
2.207 - self.saved_value_pos = None
2.208 + "Ignore the active value in 'register'."
2.209 +
2.210 + if self.saved_value_op.has_key(register):
2.211 + del self.saved_value_op[register]
2.212 + del self.saved_value_block[register]
2.213 + del self.saved_value_pos[register]
2.214
2.215 # Optimisation tests.
2.216
2.217 @@ -290,13 +344,13 @@
2.218
2.219 "Return whether the active instruction provides a constant input."
2.220
2.221 - return self.get_active_value() and self.is_constant_input(self.get_active_value())
2.222 + return self.get_active_value("working") and self.is_constant_input(self.get_active_value("working"))
2.223
2.224 def have_simple_input(self):
2.225
2.226 "Return whether the active instruction provides a simple input."
2.227
2.228 - return self.get_active_value() and self.is_simple_input(self.get_active_value())
2.229 + return self.get_active_value("working") and self.is_simple_input(self.get_active_value("working"))
2.230
2.231 # Indicate whether the active instruction can be used in place of access
2.232 # to a temporary variable retaining the result of the last instruction.
2.233 @@ -313,7 +367,7 @@
2.234 if not (isinstance(unit, Function) and unit.is_method()):
2.235 return 0
2.236
2.237 - expr = self.get_active_value()
2.238 + expr = self.get_active_value("working")
2.239 return expr and isinstance(expr, LoadName) and expr.attr.name == "self"
2.240
2.241 def have_correct_self_for_target(self, context, unit):
2.242 @@ -358,7 +412,7 @@
2.243 """
2.244
2.245 if self.should_optimise_constant_accessor() and self.have_constant_input():
2.246 - value = self.get_active_value()
2.247 + value = self.get_active_value("working")
2.248
2.249 # Get the details of the access.
2.250
2.251 @@ -388,7 +442,7 @@
2.252 """
2.253
2.254 if self.should_optimise_known_target() and self.have_constant_input():
2.255 - value = self.get_active_value()
2.256 + value = self.get_active_value("working")
2.257 target = value.attr.get_value()
2.258 context = value.attr.get_context()
2.259
2.260 @@ -434,7 +488,7 @@
2.261
2.262 # Remove the active value contributor if possible.
2.263
2.264 - removed = self.remove_active_value()
2.265 + removed = self.remove_active_value("working")
2.266 if removed is not None:
2.267
2.268 # Extend the lifetime of any temporary storage location.
2.269 @@ -445,12 +499,12 @@
2.270 # Otherwise, just leave it in place, but return the instruction.
2.271
2.272 else:
2.273 - return self.get_active_value()
2.274 + return self.get_active_value("working")
2.275
2.276 # Or provisional temporary instructions.
2.277
2.278 - elif self.saved_value_op is not None:
2.279 - return self.saved_value_op
2.280 + elif self.saved_value_op.has_key("working"):
2.281 + return self.saved_value_op["working"]
2.282
2.283 return self.translation.get_temp()
2.284
2.285 @@ -469,7 +523,7 @@
2.286 "Discard results which will not be used."
2.287
2.288 if self.should_optimise_unused_results() and self.have_simple_input():
2.289 - self.remove_active_value()
2.290 + self.remove_active_value("working")
2.291
2.292 def optimise_unused_handlers(self, instruction):
2.293
3.1 --- a/micropython/trans.py Mon Feb 06 19:06:46 2012 +0100
3.2 +++ b/micropython/trans.py Sun Feb 26 19:36:56 2012 +0100
3.3 @@ -143,7 +143,7 @@
3.4 if attrname == "__class__":
3.5 if isinstance(target, Class):
3.6 if AddressInstruction is LoadAddress:
3.7 - self.replace_active_value(LoadAddress(self.get_builtin("type")))
3.8 + self.replace_active_value("working", LoadAddress(self.get_builtin("type")))
3.9 return
3.10 else:
3.11 raise TranslateError("Assigning to __class__ is not permitted.")
3.12 @@ -171,7 +171,7 @@
3.13 # information required by the replacement instructions.
3.14
3.15 else:
3.16 - self.replace_active_value(AddressInstruction(attr))
3.17 + self.replace_active_value("working", AddressInstruction(attr))
3.18 else:
3.19 raise TranslateError("Storing of class or module attribute %r via an object is not permitted." % attrname)
3.20