1.1 --- a/micropython/ast.py Sun Aug 21 21:38:56 2011 +0200
1.2 +++ b/micropython/ast.py Sun Aug 21 23:59:52 2011 +0200
1.3 @@ -824,11 +824,7 @@
1.4 else:
1.5 self.dispatch(compiler.ast.Name("None"))
1.6
1.7 - # NOTE: Cannot guarantee that all active instructions can be set.
1.8 - #self.set_target("result")
1.9 -
1.10 - self.new_op(Transfer(source="working", target="result"))
1.11 - self.new_op(Transfer(source="working_context", target="result_context"))
1.12 + self.set_target("result")
1.13
1.14 if self.in_exception_handler:
1.15 self.new_op(ClearException(target="exception"))
2.1 --- a/micropython/code.py Sun Aug 21 21:38:56 2011 +0200
2.2 +++ b/micropython/code.py Sun Aug 21 23:59:52 2011 +0200
2.3 @@ -80,11 +80,20 @@
2.4
2.5 return Block()
2.6
2.7 - def set_block(self, block):
2.8 + def get_block(self):
2.9 +
2.10 + "Return the current block."
2.11 +
2.12 + return self.blocks[-1]
2.13
2.14 - "Add the given 'block' to the unit's list of blocks."
2.15 + def set_block(self, block, preceding=None):
2.16
2.17 - self.optimiser.reset()
2.18 + """
2.19 + Add the given 'block' to the unit's list of blocks, noting any active
2.20 + value information from 'preceding' blocks on the new block.
2.21 + """
2.22 +
2.23 + self.optimiser.reset(block, preceding)
2.24 self.blocks.append(block)
2.25
2.26 def get_loop_blocks(self):
3.1 --- a/micropython/opt.py Sun Aug 21 21:38:56 2011 +0200
3.2 +++ b/micropython/opt.py Sun Aug 21 23:59:52 2011 +0200
3.3 @@ -53,9 +53,9 @@
3.4
3.5 self.active = None
3.6
3.7 - # The instruction providing the active value.
3.8 + # Instructions providing the active value.
3.9
3.10 - self.active_value = None
3.11 + self.active_values = set()
3.12
3.13 def get_attribute_store_instructions(self):
3.14
3.15 @@ -75,12 +75,30 @@
3.16 None
3.17 )
3.18
3.19 - def reset(self):
3.20 + def reset(self, block=None, blocks=None):
3.21 +
3.22 + """
3.23 + Reset the optimiser for the given 'block' (or the current block),
3.24 + clearing the active value instructions if no 'blocks' are given, or
3.25 + collecting the active instructions from each of the blocks otherwise.
3.26 + """
3.27 +
3.28 + self.clear_active()
3.29 +
3.30 + # Make a new collection of instructions for a new block.
3.31
3.32 - "Reset the optimiser, clearing the active instructions."
3.33 + if block:
3.34 + self.active_values = set()
3.35 + block.set_active_values(self.active_values)
3.36 +
3.37 + # Otherwise, clear the collection for an existing block.
3.38
3.39 - self.clear_active_value()
3.40 - self.clear_active()
3.41 + else:
3.42 + self.active_values.clear()
3.43 +
3.44 + if blocks:
3.45 + for b in blocks:
3.46 + self.active_values.update(b.get_active_values())
3.47
3.48 def set_new(self, op):
3.49
3.50 @@ -94,13 +112,17 @@
3.51 "Set the value-providing active instruction."
3.52
3.53 if isinstance(op, current_value_instructions) and op.target == "working":
3.54 - self.active_value = op
3.55 + self.active_values.clear()
3.56 + self.active_values.add(op)
3.57
3.58 - def clear_active_value(self):
3.59 + def get_active_value(self):
3.60
3.61 - "Clear the value-providing active instruction."
3.62 + "Get any single active value or None if none or more than one exist."
3.63
3.64 - self.active_value = None
3.65 + if len(self.active_values) == 1:
3.66 + return list(self.active_values)[0]
3.67 + else:
3.68 + return None
3.69
3.70 def remove_active_value(self):
3.71
3.72 @@ -109,7 +131,7 @@
3.73 if appropriate, but keep a record of the active instruction itself.
3.74 """
3.75
3.76 - if self.active_value is self.active:
3.77 + if self.active in self.active_values:
3.78 removed = self.active
3.79 self.translation.remove_op()
3.80 return removed
3.81 @@ -120,8 +142,8 @@
3.82
3.83 "Set the target of the active instruction to 'target'."
3.84
3.85 - if self.active is not None:
3.86 - self.active.target = target
3.87 + for expr in self.active_values:
3.88 + expr.target = target
3.89
3.90 def set_active(self, op):
3.91
3.92 @@ -227,15 +249,13 @@
3.93
3.94 "Return whether the active instruction provides a constant input."
3.95
3.96 - return self.is_constant_input(self.active_value)
3.97 -
3.98 - have_known_target = have_constant_input
3.99 + return self.get_active_value() and self.is_constant_input(self.get_active_value())
3.100
3.101 def have_simple_input(self):
3.102
3.103 "Return whether the active instruction provides a simple input."
3.104
3.105 - return self.is_simple_input(self.active_value)
3.106 + return self.get_active_value() and self.is_simple_input(self.get_active_value())
3.107
3.108 def have_self_input(self, unit):
3.109
3.110 @@ -244,18 +264,16 @@
3.111 given 'unit'.
3.112 """
3.113
3.114 - return isinstance(unit, Function) and \
3.115 - unit.is_method() and isinstance(self.active_value, LoadName) and \
3.116 - self.active_value.attr.name == "self"
3.117 -
3.118 - def have_temp_compatible_access(self):
3.119 + if not (isinstance(unit, Function) and unit.is_method()):
3.120 + return 0
3.121
3.122 - """
3.123 - Indicate whether the active instruction can be used in place of access
3.124 - to a temporary variable retaining the result of the last instruction.
3.125 - """
3.126 + expr = self.get_active_value()
3.127 + return expr and isinstance(expr, LoadName) and expr.attr.name == "self"
3.128
3.129 - return isinstance(self.active_value, (LoadName, LoadTemp, LoadAddress, LoadConst, LoadClass, LoadFunction))
3.130 + # Indicate whether the active instruction can be used in place of access
3.131 + # to a temporary variable retaining the result of the last instruction.
3.132 +
3.133 + have_temp_compatible_access = have_simple_input
3.134
3.135 def have_correct_self_for_target(self, context, unit):
3.136
3.137 @@ -299,7 +317,7 @@
3.138 """
3.139
3.140 if self.should_optimise_constant_accessor() and self.have_constant_input():
3.141 - value = self.active_value
3.142 + value = self.get_active_value()
3.143
3.144 # Get the details of the access.
3.145
3.146 @@ -328,8 +346,8 @@
3.147 appropriate, get information about the specific initialiser.
3.148 """
3.149
3.150 - if self.should_optimise_known_target() and self.have_known_target():
3.151 - value = self.active_value
3.152 + if self.should_optimise_known_target() and self.have_constant_input():
3.153 + value = self.get_active_value()
3.154 target = value.attr.get_value()
3.155 context = value.attr.get_context()
3.156
4.1 --- a/micropython/program.py Sun Aug 21 21:38:56 2011 +0200
4.2 +++ b/micropython/program.py Sun Aug 21 23:59:52 2011 +0200
4.3 @@ -3,7 +3,7 @@
4.4 """
4.5 Program code and data representations.
4.6
4.7 -Copyright (C) 2009 Paul Boddie <paul@boddie.org.uk>
4.8 +Copyright (C) 2009, 2011 Paul Boddie <paul@boddie.org.uk>
4.9
4.10 This program is free software; you can redistribute it and/or modify it under
4.11 the terms of the GNU General Public License as published by the Free Software
4.12 @@ -26,10 +26,17 @@
4.13 def __init__(self):
4.14 self.code = []
4.15 self.location = None
4.16 + self.active_values = set()
4.17
4.18 def __repr__(self):
4.19 return "Block(%r, location=%r)" % (id(self), self.location)
4.20
4.21 + def set_active_values(self, values):
4.22 + self.active_values = values
4.23 +
4.24 + def get_active_values(self):
4.25 + return self.active_values
4.26 +
4.27 class DataValue:
4.28
4.29 "A representation of a raw program value."
5.1 --- a/micropython/trans.py Sun Aug 21 21:38:56 2011 +0200
5.2 +++ b/micropython/trans.py Sun Aug 21 23:59:52 2011 +0200
5.3 @@ -856,7 +856,9 @@
5.4 self.new_op(temp)
5.5 self.new_op(StoreCallable(source="source"))
5.6
5.7 - self.new_op(temp)
5.8 + # Prevent the above instruction from being modified.
5.9 +
5.10 + self.new_op(temp.copy())
5.11 #self.discard_temp(temp)
5.12 else:
5.13 self.new_op(LoadFunction(fn))
5.14 @@ -931,12 +933,7 @@
5.15 if not fn.is_lambda():
5.16 self.dispatch(compiler.ast.Name("None"))
5.17
5.18 - # NOTE: Cannot guarantee that all active instructions can be set.
5.19 - #self.set_target("result")
5.20 -
5.21 - self.new_op(Transfer(source="working", target="result"))
5.22 - self.new_op(Transfer(source="working_context", target="result_context"))
5.23 -
5.24 + self.set_target("result")
5.25 self.new_op(Return())
5.26
5.27 # Make sure that enough frame space is reserved from the start.
5.28 @@ -1301,6 +1298,7 @@
5.29 boolean status.
5.30 """
5.31
5.32 + false_block = self.get_block()
5.33 true_block = self.new_block()
5.34 end_block = self.new_block()
5.35
5.36 @@ -1311,7 +1309,7 @@
5.37 self.set_block(true_block)
5.38 self.new_op(LoadConst(self.importer.get_predefined_constant("True")))
5.39
5.40 - self.set_block(end_block)
5.41 + self.set_block(end_block, [false_block, true_block])
5.42
5.43 def _visitPrint(self, node, function_name):
5.44 self._startCallFunc()