Commits

Ronan Lamy committed 29863a1

Make partial evaluation of flowspace Blocks possible.

Comments (0)

Files changed (3)

rpython/flowspace/operation.py

     def constfold(self):
         return None
 
+    def subs(self, mapping):
+        newargs = [mapping.get(v, v) for v in self.args]
+        return self.rebuild(*newargs)
+
+    @classmethod
+    def rebuild(cls, *args):
+        newop = cls(*args)
+        result = newop.constfold()
+        if result is None:
+            return newop
+        else:
+            return result
+
+
+
 class PureOperation(HLOperation):
     pure = True
 

rpython/flowspace/simplify.py

+"""Simplification routines for flowspace flow graphs"""
+from rpython.flowspace.model import Constant, Variable, Block
+
+def eval_block(block, args):
+    """
+    Partially evaluate ``block`` by substituting ``args`` for its inputargs
+    """
+    assert len(args) == len(block.inputargs)
+    mapping = dict(zip(block.inputargs, args))
+    newargs = set(arg for arg in args if isinstance(arg, Variable))
+    newblock = Block(newargs)
+    for op in block.operations:
+        newop = op.subs(mapping)
+        if isinstance(newop, Constant):
+            mapping[op.result] = newop
+        else:
+            newblock.operations.append(newop)
+            newop.result.rename(op.result)
+    switch = block.exitswitch
+    try:
+        result = mapping[switch]
+        if isinstance(result, Constant):
+            # XXX: do something!
+            pass
+    except KeyError:
+        pass
+    newblock.exitswitch = switch
+    subst = lambda arg: mapping.get(arg, arg)
+    newexits = [link.copy(rename=subst) for link in block.exits]
+    newblock.closeblock(*newexits)
+    return newblock

rpython/flowspace/test/test_simplify.py

+from rpython.flowspace.model import Constant, Variable, Block, Link
+from rpython.flowspace.simplify import eval_block
+from rpython.flowspace.operation import op
+
+def test_simple_eval():
+    v1, v2 = Variable(), Variable()
+    block = Block([v1, v2])
+    op1 = op.mul(v1, Constant(3))
+    op2 = op.add(op1.result, Constant(1))
+    block.operations = [op1, op2]
+    block.closeblock(Link([op2.result, v2], None))
+    block2 = eval_block(block, [Constant(7), v2])
+    assert block2.inputargs == [v2]
+    assert not block2.operations
+    link, = block2.exits
+    assert link.args == [Constant(22), v2]