[pypy-svn] r66248 - in pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp: . test
arigo at codespeak.net
arigo at codespeak.net
Wed Jul 15 21:17:51 CEST 2009
Author: arigo
Date: Wed Jul 15 21:17:49 2009
New Revision: 66248
Added:
pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimize.py
- copied, changed from r66241, pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimize4.py
pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimize.py
- copied, changed from r66241, pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimize4.py
Log:
Start writing the new version of optimize.py.
So far, only find_nodes is implemented.
Work in progress.
Copied: pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimize.py (from r66241, pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimize4.py)
==============================================================================
--- pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimize4.py (original)
+++ pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimize.py Wed Jul 15 21:17:49 2009
@@ -1,16 +1,7 @@
-from pypy.jit.metainterp.resoperation import rop
-from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt, BoxPtr,
- ResOperation, AbstractDescr,
- Options, AbstractValue, ConstPtr,
- ConstObj)
-from pypy.jit.metainterp.specnode4 import (FixedClassSpecNode,
- prebuiltNotSpecNode,
- VirtualInstanceSpecNode)
-from pypy.jit.metainterp import executor
-from pypy.rlib.objectmodel import we_are_translated
-from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rpython.ootypesystem import ootype
from pypy.rlib.objectmodel import r_dict
+from pypy.rlib.unroll import unrolling_iterable
+from pypy.jit.metainterp import resoperation
+from pypy.jit.metainterp.history import AbstractValue
def av_eq(self, other):
@@ -19,559 +10,130 @@
def av_hash(self):
return self.sort_key()
+def av_newdict():
+ return r_dict(av_eq, av_hash)
+
+def _findall(Class, name_prefix):
+ result = []
+ for value, name in resoperation.opname.items():
+ if hasattr(Class, name_prefix + name):
+ result.append((value, getattr(Class, name_prefix + name)))
+ return unrolling_iterable(result)
+
+# ____________________________________________________________
+
class InstanceNode(object):
- def __init__(self, source, escaped=True, startbox=False):
- self.source = source # a Box
+ """For the first phase: InstanceNode is used to match the start and
+ the end of the loop, so it contains both 'origfields' that represents
+ the field's status at the start and 'curfields' that represents it
+ at the current point (== the end when the first phase is complete).
+ """
+ origfields = None # optimization; equivalent to an empty dict
+ curfields = None # optimization; equivalent to an empty dict
+ dependencies = None
+
+ def __init__(self, escaped, startbox=False):
self.escaped = escaped
self.startbox = startbox
- self.virtual = False
- self.const = isinstance(source, Const) # forced to True by guard_value
- self.cls = None
- self.origfields = r_dict(av_eq, av_hash)
- self.curfields = r_dict(av_eq, av_hash)
-
- def is_nonzero(self):
- return self.cls is not None or (self.const and self.source.get_() != 0)
-
- def is_zero(self):
- return self.const and self.source.get_() == 0
-
- def escape_if_startbox(self, memo, cpu):
- if self in memo:
- return
- memo[self] = None
- if self.startbox:
- self.escaped = True
- for node in self.curfields.values():
- node.escape_if_startbox(memo, cpu)
- def add_to_dependency_graph(self, other, dep_graph):
- dep_graph.append((self, other))
- for ofs, node in self.origfields.items():
- if ofs in other.curfields:
- node.add_to_dependency_graph(other.curfields[ofs], dep_graph)
-
- def intersect(self, other, nodes):
- if not other.cls:
- return prebuiltNotSpecNode
- if self.cls:
- if not self.cls.source.equals(other.cls.source):
- return prebuiltNotSpecNode
- known_class = self.cls.source
- else:
- known_class = other.cls.source
- if other.escaped:
- if self.cls is None:
- return prebuiltNotSpecNode
- return FixedClassSpecNode(known_class)
- else:
- assert self is not other
- fields = []
- d = other.curfields
- lst = d.keys()
- sort_descrs(lst)
- for ofs in lst:
- node = d[ofs]
- if ofs not in self.origfields:
- box = node.source.clonebox()
- self.origfields[ofs] = InstanceNode(box, escaped=False)
- self.origfields[ofs].cls = node.cls
- nodes[box] = self.origfields[ofs]
- specnode = self.origfields[ofs].intersect(node, nodes)
- fields.append((ofs, specnode))
- return VirtualInstanceSpecNode(known_class, fields)
+ def add_escape_dependency(self, other):
+ assert not self.escaped
+ if self.dependencies is None:
+ self.dependencies = []
+ self.dependencies.append(other)
+
+ def mark_escaped(self):
+ # invariant: if escaped=True, then dependencies is None
+ if not self.escaped:
+ self.escaped = True
+ if self.dependencies is not None:
+ deps = self.dependencies
+ self.dependencies = None
+ for box in deps:
+ box.mark_escaped()
def __repr__(self):
flags = ''
- if self.escaped: flags += 'e'
- if self.startbox: flags += 's'
- if self.const: flags += 'c'
- if self.virtual: flags += 'v'
- return "<InstanceNode %s (%s)>" % (self.source, flags)
-
-def optimize_loop(options, old_loops, loop, cpu=None):
- if not options.specialize: # for tests only
- if old_loops:
- return old_loops[0]
- else:
- return None
+ if self.escaped: flags += 'e'
+ if self.startbox: flags += 's'
+ return "<InstanceNode (%s)>" % (flags,)
+
+
+class PerfectSpecializationFinder(object):
- # This does "Perfect specialization" as per doc/jitpl5.txt.
- perfect_specializer = PerfectSpecializer(loop, options, cpu)
- perfect_specializer.find_nodes()
- perfect_specializer.intersect_input_and_output()
- for old_loop in old_loops:
- if perfect_specializer.match_exactly(old_loop):
- return old_loop
- perfect_specializer.optimize_loop()
- return None
-
-def optimize_bridge(options, old_loops, loop, cpu=None):
- if not options.specialize: # for tests only
- return old_loops[0]
-
- perfect_specializer = PerfectSpecializer(loop, options, cpu)
- perfect_specializer.find_nodes()
- for old_loop in old_loops:
- if perfect_specializer.match(old_loop):
- # xxx slow, maybe
- # XXX the next loop is a big hack. Ideally it should set cls=None
- # to prevent assuming something about the cls -- but only if there
- # is no code in the previous loop that checks the cls.
- for node in perfect_specializer.nodes.values():
- if node.startbox:
- node.cls = None
- assert not node.virtual
- perfect_specializer.propagate_escapes()
- perfect_specializer.adapt_for_match(old_loop)
- perfect_specializer.optimize_loop()
- return old_loop
- return None # no loop matches
-
-class PerfectSpecializer(object):
- _allow_automatic_node_creation = False
-
- def __init__(self, loop, options=Options(), cpu=None):
- self.loop = loop
- self.options = options
- self.cpu = cpu
- self.nodes = {}
- self.dependency_graph = []
+ def __init__(self):
+ self.nodes = {} # Box -> InstanceNode
+ self.node_escaped = InstanceNode(escaped=True)
+
+ def clear(self):
+ self.nodes.clear()
def getnode(self, box):
- try:
- return self.nodes[box]
- except KeyError:
- if isinstance(box, Const):
- node = InstanceNode(box, escaped=True)
+ return self.nodes.get(box, self.node_escaped)
+
+ def find_nodes(self, loop):
+ self.clear()
+ for box in loop.inputargs:
+ self.nodes[box] = InstanceNode(escaped=False, startbox=True)
+ #
+ for op in loop.operations:
+ opnum = op.opnum
+ for value, func in find_nodes_ops:
+ if opnum == value:
+ func(self, op)
+ break
else:
- assert self._allow_automatic_node_creation
- node = InstanceNode(box, escaped=True, startbox=True)
- self.nodes[box] = node
- return node
-
- def getsource(self, box):
- if isinstance(box, Const):
- return box
- return self.nodes[box].source
-
- def find_nodes_setfield(self, instnode, ofs, fieldnode):
- assert isinstance(ofs, AbstractValue)
- instnode.curfields[ofs] = fieldnode
- self.dependency_graph.append((instnode, fieldnode))
+ self.find_nodes_default(op)
- def find_nodes_getfield(self, instnode, field, box):
+ def find_nodes_default(self, op):
+ if not op.has_no_side_effect():
+ # default case: mark the arguments as escaping
+ for box in op.args:
+ self.getnode(box).mark_escaped()
+
+ def find_nodes_NEW_WITH_VTABLE(self, op):
+ self.nodes[op.result] = InstanceNode(escaped=False)
+
+ def find_nodes_SETFIELD_GC(self, op):
+ instnode = self.getnode(op.args[0])
+ if instnode.escaped:
+ return # nothing to be gained from tracking the field
+ fieldnode = self.getnode(op.args[1])
+ field = op.descr
+ assert isinstance(field, AbstractValue)
+ if instnode.curfields is None:
+ instnode.curfields = av_newdict()
+ instnode.curfields[field] = fieldnode
+ instnode.add_escape_dependency(fieldnode)
+
+ def find_nodes_GETFIELD_GC(self, op):
+ instnode = self.getnode(op.args[0])
+ if instnode.escaped:
+ return # nothing to be gained from tracking the field
+ field = op.descr
assert isinstance(field, AbstractValue)
- if field in instnode.curfields:
+ if instnode.curfields is not None and field in instnode.curfields:
fieldnode = instnode.curfields[field]
- elif field in instnode.origfields:
+ elif instnode.origfields is not None and field in instnode.origfields:
fieldnode = instnode.origfields[field]
else:
- fieldnode = InstanceNode(box, escaped=False)
- if instnode.startbox:
- fieldnode.startbox = True
- self.dependency_graph.append((instnode, fieldnode))
+ fieldnode = InstanceNode(escaped=False, startbox=instnode.startbox)
+ instnode.add_escape_dependency(fieldnode)
+ if instnode.origfields is None:
+ instnode.origfields = av_newdict()
instnode.origfields[field] = fieldnode
- self.nodes[box] = fieldnode
+ self.nodes[op.result] = fieldnode
- def find_nodes(self):
- # Steps (1) and (2)
- if self.loop.inputargs is not None:
- for box in self.loop.inputargs:
- self.nodes[box] = InstanceNode(box, escaped=False,
- startbox=True)
- else:
- self._allow_automatic_node_creation = True
- #
- for op in self.loop.operations:
- #print '| ' + op.repr()
- if op.is_guard():
- self.find_nodes_guard(op)
- opnum = op.opnum
- if opnum == rop.JUMP:
- break
- elif opnum == rop.NEW_WITH_VTABLE:
- box = op.result
- instnode = InstanceNode(box, escaped=False)
- instnode.cls = InstanceNode(op.args[0])
- self.nodes[box] = instnode
- continue
- elif opnum == rop.SETFIELD_GC:
- instnode = self.getnode(op.args[0])
- field = op.descr
- self.find_nodes_setfield(instnode, field,
- self.getnode(op.args[1]))
- continue
- elif opnum == rop.GETFIELD_GC:
- instnode = self.getnode(op.args[0])
- field = op.descr
- box = op.result
- self.find_nodes_getfield(instnode, field, box)
- continue
- elif opnum == rop.GETFIELD_GC_PURE:
- instnode = self.getnode(op.args[0])
- field = op.descr
- if not instnode.const:
- box = op.result
- self.find_nodes_getfield(instnode, field, box)
- continue
- elif opnum == rop.GUARD_CLASS:
- instnode = self.getnode(op.args[0])
- if instnode.cls is None:
- instnode.cls = InstanceNode(op.args[1])
- continue
- elif op.is_always_pure():
- is_pure = True
- for arg in op.args:
- if not self.getnode(arg).const:
- is_pure = False
- if is_pure:
- box = op.result
- assert box is not None
- self.nodes[box] = InstanceNode(box.constbox(),
- escaped=True)
- continue
- elif not op.has_no_side_effect():
- # default case
- for box in op.args:
- if isinstance(box, Box):
- self.getnode(box).escaped = True
- box = op.result
- if box is not None:
- self.nodes[box] = InstanceNode(box, escaped=True)
-
- def find_nodes_guard(self, op):
- assert len(op.suboperations) == 1
- for arg in op.suboperations[0].args:
- self.getnode(arg)
-
- def recursively_find_escaping_values(self):
- end_args = self.loop.operations[-1].args
- assert len(self.loop.inputargs) == len(end_args)
- memo = {}
- for i in range(len(end_args)):
- end_box = end_args[i]
- if isinstance(end_box, Box):
- self.nodes[end_box].escape_if_startbox(memo, self.cpu)
- for i in range(len(end_args)):
- box = self.loop.inputargs[i]
- other_box = end_args[i]
- if isinstance(other_box, Box):
- self.nodes[box].add_to_dependency_graph(self.nodes[other_box],
- self.dependency_graph)
- self.propagate_escapes()
-
- def propagate_escapes(self):
- # XXX find efficient algorithm, we're too fried for that by now
- done = False
- while not done:
- done = True
- for instnode, fieldnode in self.dependency_graph:
- if instnode.escaped: ## and not instnode.virtualized:
- if not fieldnode.escaped:
- fieldnode.escaped = True
- done = False
-
- def intersect_input_and_output(self):
- # Step (3)
- self.recursively_find_escaping_values()
- jump = self.loop.operations[-1]
- assert jump.opnum == rop.JUMP
- specnodes = []
- for i in range(len(self.loop.inputargs)):
- enternode = self.nodes[self.loop.inputargs[i]]
- leavenode = self.getnode(jump.args[i])
- specnodes.append(enternode.intersect(leavenode, self.nodes))
- self.specnodes = specnodes
-
- def expanded_version_of(self, boxlist):
- newboxlist = []
- assert len(boxlist) == len(self.specnodes)
- for i in range(len(boxlist)):
- box = boxlist[i]
- specnode = self.specnodes[i]
- specnode.expand_boxlist(self.nodes[box], newboxlist)
- return newboxlist
-
- def prepare_rebuild_ops(self, instnode, rebuild_ops, memo, box=None):
- if box is None:
- box = instnode.source
- if not isinstance(box, Box):
- return box
- if box in memo:
- return box
- if instnode.virtual:
- ld = instnode.cls.source
- if self.cpu.is_oo and isinstance(ld, ConstObj):
- # it's probably a ootype new
- cls = ld.getobj()
- typedescr = self.cpu.class_sizes[cls] # XXX this is probably not rpython
- op = ResOperation(rop.NEW_WITH_VTABLE, [ld], box,
- descr=typedescr)
- else:
- assert not self.cpu.is_oo
- vtable = ld.getint()
- if self.cpu.translate_support_code:
- vtable_addr = self.cpu.cast_int_to_adr(vtable)
- size = self.cpu.class_sizes[vtable_addr]
- else:
- size = self.cpu.class_sizes[vtable]
- op = ResOperation(rop.NEW_WITH_VTABLE, [ld], box,
- descr=size)
- rebuild_ops.append(op)
- memo[box] = None
- for ofs, node in instnode.curfields.items():
- fieldbox = self.prepare_rebuild_ops(node, rebuild_ops, memo)
- assert isinstance(ofs, AbstractDescr)
- op = ResOperation(rop.SETFIELD_GC, [box, fieldbox],
- None, descr=ofs)
- rebuild_ops.append(op)
- return box
- memo[box] = None
- return box
-
- def optimize_guard(self, op):
- # Make a list of operations to run to rebuild the unoptimized objects.
- rebuild_ops = []
- memo = {}
- assert len(op.suboperations) == 1
- op_fail = op.suboperations[0]
- assert op_fail.opnum == rop.FAIL
- for box in op_fail.args:
- if isinstance(box, Const):
- continue
- self.prepare_rebuild_ops(self.nodes[box], rebuild_ops, memo, box)
-
- newboxes = []
- for box in op_fail.args:
- if box in self.nodes:
- box = self.nodes[box].source
- newboxes.append(box)
- op_fail.args = newboxes
- # NB. we mutate op_fail in-place above. That's bad. Hopefully
- # it does not really matter because no-one is going to look again
- # at its unoptimized version. We cannot really clone it because of
- # how the rest works (e.g. it is returned by cpu.execute_operations()).
- rebuild_ops.append(op_fail)
- op1 = op.clone()
- op1.args = self.new_arguments(op1)
- op1.suboperations = rebuild_ops
- op.optimized = op1
- return op1
-
- def new_arguments(self, op):
- newboxes = []
- for box in op.args:
- if isinstance(box, Box):
- instnode = self.nodes[box]
- assert not instnode.virtual
- box = instnode.source
- newboxes.append(box)
- return newboxes
-
- def optimize_getfield(self, instnode, ofs, box):
- assert isinstance(ofs, AbstractValue)
- if instnode.virtual:
- assert ofs in instnode.curfields
- return True # this means field is never actually
- return False
-
- def optimize_setfield(self, instnode, ofs, valuenode, valuebox):
- assert isinstance(ofs, AbstractValue)
- if instnode.virtual: ## or instnode.virtualized:
- instnode.curfields[ofs] = valuenode
- return True
- else:
- assert not valuenode.virtual
- return False
- # we never perform this operation here, note
-
- def optimize_loop(self):
- self._allow_automatic_node_creation = False
- newoperations = []
- exception_might_have_happened = False
- if self.loop.inputargs is not None:
- # closing a loop
- assert len(self.loop.inputargs) == len(self.specnodes)
- for i in range(len(self.specnodes)):
- box = self.loop.inputargs[i]
- self.specnodes[i].mutate_nodes(self.nodes[box])
- newinputargs = self.expanded_version_of(self.loop.inputargs)
- else:
- # making a bridge
- newinputargs = None
- #
- for op in self.loop.operations:
- opnum = op.opnum
- if opnum == rop.JUMP:
- args = self.expanded_version_of(op.args)
- for arg in args:
- if arg in self.nodes:
- assert not self.nodes[arg].virtual
- op = op.clone()
- op.args = args
- newoperations.append(op)
- break
- elif opnum == rop.GUARD_NO_EXCEPTION:
- if not exception_might_have_happened:
- continue
- exception_might_have_happened = False
- newoperations.append(self.optimize_guard(op))
- continue
- elif opnum == rop.GUARD_EXCEPTION:
- newoperations.append(self.optimize_guard(op))
- continue
- elif (opnum == rop.GUARD_TRUE or
- opnum == rop.GUARD_FALSE):
- instnode = self.nodes[op.args[0]]
- if instnode.const:
- continue
- newoperations.append(self.optimize_guard(op))
- continue
- elif opnum == rop.GUARD_CLASS:
- instnode = self.nodes[op.args[0]]
- if instnode.cls is not None:
- assert op.args[1].equals(instnode.cls.source)
- continue
- instnode.cls = InstanceNode(op.args[1])
- newoperations.append(self.optimize_guard(op))
- continue
- elif opnum == rop.GUARD_VALUE:
- instnode = self.nodes[op.args[0]]
- assert isinstance(op.args[1], Const)
- if instnode.const:
- continue
- instnode.const = True
- newoperations.append(self.optimize_guard(op))
- continue
- elif opnum == rop.GETFIELD_GC:
- instnode = self.nodes[op.args[0]]
- if self.optimize_getfield(instnode, op.descr, op.result):
- continue
- # otherwise we need this getfield, but it does not
- # invalidate caches
- elif opnum == rop.GETFIELD_GC_PURE:
- instnode = self.nodes[op.args[0]]
- if not instnode.const:
- if self.optimize_getfield(instnode, op.descr, op.result):
- continue
- elif opnum == rop.NEW_WITH_VTABLE:
- # self.nodes[op.result] keeps the value from Steps (1,2)
- instnode = self.nodes[op.result]
- instnode.curfields = r_dict(av_eq, av_hash)
- if not instnode.escaped:
- instnode.virtual = True
- assert instnode.cls is not None
- continue
- elif opnum == rop.SETFIELD_GC:
- instnode = self.nodes[op.args[0]]
- valuenode = self.nodes[op.args[1]]
- ofs = op.descr
- if self.optimize_setfield(instnode, ofs, valuenode, op.args[1]):
- continue
- elif (opnum == rop.OOISNULL or
- opnum == rop.OONONNULL):
- instnode = self.getnode(op.args[0])
- # we know the result is constant if instnode is a virtual,
- # or known to be non-zero.
- if instnode.virtual or instnode.is_nonzero():
- box = op.result
- instnode = InstanceNode(box.constbox())
- self.nodes[box] = instnode
- continue
- elif (opnum == rop.OOIS or
- opnum == rop.OOISNOT):
- instnode_x = self.getnode(op.args[0])
- instnode_y = self.getnode(op.args[1])
- # we know the result is constant in one of these 5 cases:
- if (instnode_x.virtual or # x is a virtual (even if y isn't)
- instnode_y.virtual or # y is a virtual (even if x isn't)
- # x != NULL and y == NULL
- (instnode_x.is_nonzero() and instnode_y.is_zero()) or
- # x == NULL and y != NULL
- (instnode_x.is_zero() and instnode_y.is_nonzero()) or
- # x == NULL and y == NULL
- (instnode_x.is_zero() and instnode_y.is_zero())):
- #
- box = op.result
- instnode = InstanceNode(box.constbox())
- self.nodes[box] = instnode
- continue
- # default handling of arguments and return value
- op = op.clone()
- op.args = self.new_arguments(op)
- if op.is_always_pure():
- for box in op.args:
- if isinstance(box, Box):
- break
- else:
- # all constant arguments: constant-fold away
- box = op.result
- assert box is not None
- instnode = InstanceNode(box.constbox())
- self.nodes[box] = instnode
- continue
- if op.can_raise():
- exception_might_have_happened = True
- box = op.result
- if box is not None:
- instnode = InstanceNode(box)
- self.nodes[box] = instnode
- newoperations.append(op)
- #
- self.loop.specnodes = self.specnodes
- self.loop.inputargs = newinputargs
- self.loop.operations = newoperations
-
- def match_exactly(self, old_loop):
- assert len(old_loop.specnodes) == len(self.specnodes)
- for i in range(len(self.specnodes)):
- old_specnode = old_loop.specnodes[i]
- new_specnode = self.specnodes[i]
- if not old_specnode.equals(new_specnode):
- return False
- return True
-
- def match(self, old_loop):
- jump_op = self.loop.operations[-1]
- assert jump_op.opnum == rop.JUMP
- assert len(old_loop.specnodes) == len(jump_op.args)
- for i in range(len(old_loop.specnodes)):
- old_specnode = old_loop.specnodes[i]
- new_instnode = self.getnode(jump_op.args[i])
- if not old_specnode.matches(new_instnode):
- return False
- return True
-
- def adapt_for_match(self, old_loop):
- jump_op = self.loop.operations[-1]
- assert jump_op.opnum == rop.JUMP
- self.specnodes = old_loop.specnodes
- for i in range(len(old_loop.specnodes)):
- old_specnode = old_loop.specnodes[i]
- new_instnode = self.getnode(jump_op.args[i])
- old_specnode.adapt_to(new_instnode, None)
-
-# ---------------------------------------------------------------
-
-def partition(array, left, right):
- last_item = array[right]
- pivot = last_item.sort_key()
- storeindex = left
- for i in range(left, right):
- if array[i].sort_key() <= pivot:
- array[i], array[storeindex] = array[storeindex], array[i]
- storeindex += 1
- # Move pivot to its final place
- array[storeindex], array[right] = last_item, array[storeindex]
- return storeindex
-
-def quicksort(array, left, right):
- # sort array[left:right+1] (i.e. bounds included)
- if right > left:
- pivotnewindex = partition(array, left, right)
- quicksort(array, left, pivotnewindex - 1)
- quicksort(array, pivotnewindex + 1, right)
+ def find_nodes_GETFIELD_GC_PURE(self, op):
+ self.find_nodes_GETFIELD_GC(op)
+
+ def find_nodes_GUARD_CLASS(self, op):
+ pass # prevent the default handling
+
+ def find_nodes_JUMP(self, op):
+ pass # prevent the default handling
+
+find_nodes_ops = _findall(PerfectSpecializationFinder, 'find_nodes_')
+perfect_specialization_finder = PerfectSpecializationFinder()
-def sort_descrs(lst):
- quicksort(lst, 0, len(lst)-1)
+# ____________________________________________________________
Copied: pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimize.py (from r66241, pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimize4.py)
==============================================================================
--- pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimize4.py (original)
+++ pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimize.py Wed Jul 15 21:17:49 2009
@@ -8,10 +8,10 @@
from pypy.jit.metainterp.resoperation import rop
from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr,
Const, ConstAddr, TreeLoop)
-from pypy.jit.metainterp.optimize4 import PerfectSpecializer
-from pypy.jit.metainterp.specnode4 import (FixedClassSpecNode,
- NotSpecNode,
- VirtualInstanceSpecNode)
+from pypy.jit.metainterp.optimize import perfect_specialization_finder
+from pypy.jit.metainterp.specnode import (FixedClassSpecNode,
+ NotSpecNode,
+ VirtualInstanceSpecNode)
cpu = runner.LLtypeCPU(None)
@@ -80,25 +80,6 @@
opnum = getattr(rop, opname.upper())
return resoperation.ResOperation(opnum, args, result, descr)
-
-class CheckPerfectSpecializer(PerfectSpecializer):
- def optimize_loop(self):
- PerfectSpecializer.optimize_loop(self)
- check_operations(self.loop.inputargs, self.loop.operations)
-
-def check_operations(inputargs, operations, indent=' |'):
- seen = dict.fromkeys(inputargs)
- for op in operations:
- print indent, op
- for x in op.args:
- assert x in seen or isinstance(x, Const)
- assert op.descr is None or isinstance(op.descr, history.AbstractDescr)
- if op.is_guard():
- check_operations(seen.keys(), op.suboperations, indent+' ')
- if op.result is not None:
- seen[op.result] = True
- assert operations[-1].opnum in (rop.FAIL, rop.JUMP)
-
# ____________________________________________________________
class A:
@@ -126,6 +107,7 @@
ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
size_of_node),
ResOperation('setfield_gc', [n2, v2], None, ofs_value),
+ ResOperation('setfield_gc', [n2, n2], None, ofs_next),
ResOperation('jump', [sum2, n2], None),
]
@@ -136,849 +118,15 @@
set_guard(ops[0], [])
def test_A_find_nodes():
- spec = CheckPerfectSpecializer(Loop(A.inputargs, A.ops))
- spec.find_nodes()
- assert spec.nodes[A.sum] is not spec.nodes[A.sum2]
- assert spec.nodes[A.n1] is not spec.nodes[A.n2]
- assert spec.nodes[A.n1].cls.source.value == node_vtable_adr
- assert not spec.nodes[A.n1].escaped
- assert spec.nodes[A.n2].cls.source.value == node_vtable_adr
- assert not spec.nodes[A.n2].escaped
-
- assert len(spec.nodes[A.n1].curfields) == 0
- assert spec.nodes[A.n1].origfields[A.ofs_value] is spec.nodes[A.v]
- assert len(spec.nodes[A.n2].origfields) == 0
- assert spec.nodes[A.n2].curfields[A.ofs_value] is spec.nodes[A.v2]
-
-def test_A_intersect_input_and_output():
- spec = CheckPerfectSpecializer(Loop(A.inputargs, A.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- assert len(spec.specnodes) == 2
- spec_sum, spec_n = spec.specnodes
- assert isinstance(spec_sum, NotSpecNode)
- assert isinstance(spec_n, VirtualInstanceSpecNode)
- assert spec_n.known_class.value == node_vtable_adr
- assert spec_n.fields[0][0] == A.ofs_value
- assert isinstance(spec_n.fields[0][1], NotSpecNode)
-
-def test_A_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(A.inputargs, A.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- assert spec.loop.inputargs == [A.sum, A.v]
- equaloplists(spec.loop.operations, [
- ResOperation('int_sub', [A.v, ConstInt(1)], A.v2),
- ResOperation('int_add', [A.sum, A.v], A.sum2),
- ResOperation('jump', [A.sum2, A.v2], None),
- ])
-
-# ____________________________________________________________
-
-class B:
- locals().update(A.__dict__) # :-)
- inputargs = [sum, n1]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('escape', [n1], None),
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
- size_of_node),
- ResOperation('setfield_gc', [n2, v2], None, ofs_value),
- ResOperation('escape', [n2], None), # <== escaping
- ResOperation('jump', [sum2, n2], None),
- ]
- set_guard(ops[0], [])
-
-def test_B_find_nodes():
- spec = CheckPerfectSpecializer(Loop(B.inputargs, B.ops))
- spec.find_nodes()
- assert spec.nodes[B.n1].cls.source.value == node_vtable_adr
- assert spec.nodes[B.n1].escaped
- assert spec.nodes[B.n2].cls.source.value == node_vtable_adr
- assert spec.nodes[B.n2].escaped
-
-def test_B_intersect_input_and_output():
- spec = CheckPerfectSpecializer(Loop(B.inputargs, B.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- assert len(spec.specnodes) == 2
- spec_sum, spec_n = spec.specnodes
- assert isinstance(spec_sum, NotSpecNode)
- assert type(spec_n) is FixedClassSpecNode
- assert spec_n.known_class.value == node_vtable_adr
-
-def test_B_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(B.inputargs, B.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- assert spec.loop.inputargs == [B.sum, B.n1]
- equaloplists(spec.loop.operations, [
- # guard_class is gone
- ResOperation('escape', [B.n1], None),
- ResOperation('getfield_gc', [B.n1], B.v, B.ofs_value),
- ResOperation('int_sub', [B.v, ConstInt(1)], B.v2),
- ResOperation('int_add', [B.sum, B.v], B.sum2),
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], B.n2,
- B.size_of_node),
- ResOperation('setfield_gc', [B.n2, B.v2], None, B.ofs_value),
- ResOperation('escape', [B.n2], None), # <== escaping
- ResOperation('jump', [B.sum2, B.n2], None),
- ])
-
-# ____________________________________________________________
-
-class C:
- locals().update(A.__dict__) # :-)
- inputargs = [sum, n1]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('escape', [n1], None), # <== escaping
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('escape', [n1], None), # <== escaping
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
- size_of_node),
- ResOperation('setfield_gc', [n2, v2], None, ofs_value),
- ResOperation('jump', [sum2, n2], None),
- ]
- set_guard(ops[0], [])
-
-def test_C_find_nodes():
- spec = CheckPerfectSpecializer(Loop(C.inputargs, C.ops))
- spec.find_nodes()
- assert spec.nodes[C.n1].cls.source.value == node_vtable_adr
- assert spec.nodes[C.n1].escaped
- assert spec.nodes[C.n2].cls.source.value == node_vtable_adr
-
-def test_C_intersect_input_and_output():
- spec = CheckPerfectSpecializer(Loop(C.inputargs, C.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- assert spec.nodes[C.n2].escaped
- assert len(spec.specnodes) == 2
- spec_sum, spec_n = spec.specnodes
- assert isinstance(spec_sum, NotSpecNode)
- assert type(spec_n) is FixedClassSpecNode
- assert spec_n.known_class.value == node_vtable_adr
-
-def test_C_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(C.inputargs, C.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- assert spec.loop.inputargs == [C.sum, C.n1]
- equaloplists(spec.loop.operations, [
- # guard_class is gone
- ResOperation('escape', [C.n1], None), # <== escaping
- ResOperation('getfield_gc', [C.n1], C.v, C.ofs_value),
- ResOperation('int_sub', [C.v, ConstInt(1)], C.v2),
- ResOperation('int_add', [C.sum, C.v], C.sum2),
- ResOperation('escape', [C.n1], None), # <== escaping
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], C.n2,
- C.size_of_node),
- ResOperation('setfield_gc', [C.n2, C.v2], None, C.ofs_value),
- ResOperation('jump', [C.sum2, C.n2], None),
- ])
-
-# ____________________________________________________________
-
-class D:
- locals().update(A.__dict__) # :-)
- inputargs = [sum, n1]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node2_vtable, cpu)], None),
- # the only difference is different vtable ^^^^^^^^^^^^
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
- size_of_node),
- ResOperation('setfield_gc', [n2, v2], None, ofs_value),
- ResOperation('jump', [sum2, n2], None),
- ]
-
-def test_D_intersect_input_and_output():
- py.test.skip("nowadays, this compiles, just without making a virtual")
- spec = CheckPerfectSpecializer(Loop(D.inputargs, D.ops))
- spec.find_nodes()
- py.test.raises(CancelInefficientLoop, spec.intersect_input_and_output)
-
-# ____________________________________________________________
-
-class E:
- locals().update(A.__dict__) # :-)
- inputargs = [sum, n1]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
- size_of_node),
- ResOperation('setfield_gc', [n2, v2], None, ofs_value),
- ResOperation('guard_true', [v2], None),
- ResOperation('jump', [sum2, n2], None),
- ]
- set_guard(ops[0], [])
- set_guard(ops[-2], [sum2, n2])
-
-def test_E_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(E.inputargs, E.ops), cpu=cpu)
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- assert spec.loop.inputargs == [E.sum, E.v]
- equaloplists(spec.loop.operations, [
- # guard_class is gone
- ResOperation('int_sub', [E.v, ConstInt(1)], E.v2),
- ResOperation('int_add', [E.sum, E.v], E.sum2),
- ResOperation('guard_true', [E.v2], None),
- ResOperation('jump', [E.sum2, E.v2], None),
- ])
- guard_op = spec.loop.operations[-2]
- assert guard_op.getopname() == 'guard_true'
- _, n2 = guard_op.suboperations[-1].args
- equaloplists(guard_op.suboperations, [
- ResOperation('new_with_vtable', [ConstAddr(node_vtable_adr, cpu)], n2,
- E.size_of_node),
- ResOperation('setfield_gc', [n2, E.v2], None, E.ofs_value),
- ResOperation('fail', [E.sum2, n2], None),
- ])
-
-##def test_E_rebuild_after_failure():
-## spec = CheckPerfectSpecializer(Loop(E.inputargs, E.ops), cpu=cpu)
-## spec.find_nodes()
-## spec.intersect_input_and_output()
-## spec.optimize_loop()
-## guard_op = spec.loop.operations[-2]
-## v_sum_b = BoxInt(13)
-## v_v_b = BoxInt(14)
-## history = History(cpu)
-## newboxes = rebuild_boxes_from_guard_failure(guard_op, cpu, history,
-## [v_sum_b, v_v_b])
-## assert len(newboxes) == 2
-## assert newboxes[0] == v_sum_b
-## p = newboxes[1].getptr(lltype.Ptr(NODE))
-## assert p.value == 14
-## assert len(history.operations) == 2
-## assert ([op.getopname() for op in history.operations] ==
-## ['new_with_vtable', 'setfield_gc'])
-
-# ____________________________________________________________
-
-class F:
- locals().update(A.__dict__) # :-)
- nextnode = lltype.malloc(NODE)
- nextnode.value = 32
- n3 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode))
- vbool1 = BoxInt(1)
- vbool2 = BoxInt(0)
- vbool3 = BoxInt(1)
- inputargs = [sum, n1, n3]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
- size_of_node),
- ResOperation('setfield_gc', [n2, v2], None, ofs_value),
- ResOperation('ooisnot', [n2, n3], vbool1),
- ResOperation('guard_true', [vbool1], None),
- ResOperation('ooisnull', [n2], vbool2),
- ResOperation('guard_false', [vbool2], None),
- ResOperation('oononnull', [n3], vbool3),
- ResOperation('guard_true', [vbool3], None),
- ResOperation('jump', [sum2, n2, n3], None),
- ]
- set_guard(ops[0], [])
- set_guard(ops[-2], [sum2, n2, n3])
- set_guard(ops[-4], [sum2, n2, n3])
- set_guard(ops[-6], [sum2, n2, n3])
-
-def test_F_find_nodes():
- spec = CheckPerfectSpecializer(Loop(F.inputargs, F.ops))
- spec.find_nodes()
- assert not spec.nodes[F.n1].escaped
- assert not spec.nodes[F.n2].escaped
-
-def test_F_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(F.inputargs, F.ops), cpu=cpu)
- spec.find_nodes()
- spec.intersect_input_and_output()
- assert spec.nodes[F.n3].escaped
- spec.optimize_loop()
- assert spec.loop.inputargs == [F.sum, F.v, F.n3]
- equaloplists(spec.loop.operations, [
- ResOperation('int_sub', [F.v, ConstInt(1)], F.v2),
- ResOperation('int_add', [F.sum, F.v], F.sum2),
- ResOperation('oononnull', [F.n3], F.vbool3),
- ResOperation('guard_true', [F.vbool3], None),
- ResOperation('jump', [F.sum2, F.v2, F.n3], None),
- ])
-
-class F2:
- locals().update(A.__dict__) # :-)
- node2 = lltype.malloc(NODE)
- node3 = lltype.malloc(NODE)
- node4 = lltype.malloc(NODE)
- n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node2))
- n3 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node3))
- n4 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node4))
- vbool1 = BoxInt(0)
- inputargs = [n2, n3]
- ops = [
- ResOperation('oois', [n2, n3], vbool1),
- ResOperation('guard_true', [vbool1], None),
- ResOperation('escape', [], n4),
- ResOperation('jump', [n2, n4], None),
- ]
- set_guard(ops[-3], [n2])
-
-def test_F2_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(F2.inputargs, F2.ops), cpu=cpu)
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- equaloplists(spec.loop.operations, F2.ops)
-
-# ____________________________________________________________
-
-class G:
- locals().update(A.__dict__) # :-)
- v3 = BoxInt(123)
- v4 = BoxInt(124)
- inputargs = [sum, n1]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
- size_of_node),
- ResOperation('setfield_gc', [n2, ConstInt(123)], None, ofs_value),
- ResOperation('getfield_gc', [n2], v3, ofs_value),
- ResOperation('int_add', [v3, ConstInt(1)], v4),
- ResOperation('setfield_gc', [n2, v4], None, ofs_value),
- ResOperation('guard_true', [v2], None),
- ResOperation('jump', [sum2, n2], None),
- ]
- set_guard(ops[0], [])
- set_guard(ops[-2], [sum2, n2])
-
-def test_G_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(G.inputargs, G.ops), cpu=cpu)
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- assert spec.loop.inputargs == [G.sum, G.v]
- equaloplists(spec.loop.operations, [
- # guard_class is gone
- ResOperation('int_sub', [G.v, ConstInt(1)], G.v2),
- ResOperation('int_add', [G.sum, G.v], G.sum2),
- ResOperation('guard_true', [G.v2], None),
- ResOperation('jump', [G.sum2, ConstInt(124)], None),
- ])
- guard_op = spec.loop.operations[-2]
- assert guard_op.getopname() == 'guard_true'
- _, n2 = guard_op.suboperations[-1].args
- equaloplists(guard_op.suboperations, [
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
- G.size_of_node),
- ResOperation('setfield_gc', [n2, ConstInt(124)], None, G.ofs_value),
- ResOperation('fail', [G.sum2, n2], None),
- ])
-
-# ____________________________________________________________
-
-class H:
- locals().update(A.__dict__) # :-)
- #
- containernode = lltype.malloc(NODE)
- containernode.next = lltype.malloc(NODE)
- containernode.next.value = 20
- n0 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, containernode))
- n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, containernode.next))
- nextnode = lltype.malloc(NODE)
- nextnode.value = 19
- n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode))
- v = BoxInt(containernode.next.value)
- v2 = BoxInt(nextnode.value)
- inputargs = [n0]
- ops = [
- ResOperation('getfield_gc', [n0], n1, ofs_next),
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
- size_of_node),
- ResOperation('setfield_gc', [n2, v2], None, ofs_value),
- ResOperation('setfield_gc', [n0, n2], None, ofs_next),
- ResOperation('jump', [n0], None),
- ]
-
-def test_H_intersect_input_and_output():
- spec = CheckPerfectSpecializer(Loop(H.inputargs, H.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- assert spec.nodes[H.n0].escaped
- assert spec.nodes[H.n1].escaped
- assert spec.nodes[H.n2].escaped
-
-# ____________________________________________________________
-
-class I:
- locals().update(A.__dict__) # :-)
- #
- containernode = lltype.malloc(NODE)
- containernode.next = lltype.malloc(NODE)
- containernode.next.value = 20
- n0 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, containernode))
- nextnode = lltype.malloc(NODE)
- nextnode.value = 19
- n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode))
- inputargs = [n0]
- ops = [
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
- size_of_node),
- ResOperation('setfield_gc', [n2, n0], None, ofs_next),
- ResOperation('jump', [n2], None),
- ]
-
-def test_I_intersect_input_and_output():
- spec = CheckPerfectSpecializer(Loop(I.inputargs, I.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- assert spec.nodes[I.n0].escaped
- assert spec.nodes[I.n2].escaped
-
-# ____________________________________________________________
-
-class J:
- locals().update(A.__dict__) # :-)
- #
- containernode = lltype.malloc(NODE)
- containernode.next = lltype.malloc(NODE)
- containernode.next.value = 20
- n0 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, containernode))
- nextnode = lltype.malloc(NODE)
- nextnode.value = 19
- n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode))
- n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode))
- inputargs = [n0]
- ops = [
- ResOperation('getfield_gc', [n0], n1, ofs_next),
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
- size_of_node),
- ResOperation('setfield_gc', [n2, n1], None, ofs_next),
- ResOperation('jump', [n2], None),
- ]
-
-def test_J_intersect_input_and_output():
- spec = CheckPerfectSpecializer(Loop(J.inputargs, J.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- assert not spec.nodes[J.n0].escaped
- assert spec.nodes[J.n1].escaped
- assert not spec.nodes[J.n2].escaped
-
-# ____________________________________________________________
-
-class K0:
- locals().update(A.__dict__) # :-)
- sum3 = BoxInt(3)
- v3 = BoxInt(4)
- inputargs = [sum, n1]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('getfield_gc', [n1], v3, ofs_value),
- ResOperation('int_add', [sum2, v3], sum3),
- ResOperation('escape', [n1], None),
- ResOperation('jump', [sum3, n1], None),
- ]
-
-def test_K0_optimize_loop():
- py.test.skip("Disabled")
- spec = CheckPerfectSpecializer(Loop(K0.inputargs, K0.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- v4 = spec.loop.operations[-1].args[-1]
- assert spec.loop.inputargs == [K0.sum, K0.n1, K0.v]
- equaloplists(spec.loop.operations, [
- ResOperation('int_sub', [K0.v, ConstInt(1)], K0.v2),
- ResOperation('int_add', [K0.sum, K0.v], K0.sum2),
- ResOperation('int_add', [K0.sum2, K0.v], K0.sum3),
- ResOperation('escape', [K0.n1], None),
- ResOperation('getfield_gc', [K0.n1], v4, K0.ofs_value),
- ResOperation('jump', [K0.sum3, K0.n1, v4], None),
- ])
-
-
-class K1:
- locals().update(A.__dict__) # :-)
- sum3 = BoxInt(3)
- v3 = BoxInt(4)
- inputargs = [sum, n1]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('setfield_gc', [n1, sum], None, ofs_value),
- ResOperation('getfield_gc', [n1], v3, ofs_value),
- ResOperation('int_add', [sum2, v3], sum3),
- ResOperation('escape', [n1], None),
- ResOperation('jump', [sum3, n1], None),
- ]
-
-def test_K1_optimize_loop():
- py.test.skip("Disabled")
- spec = CheckPerfectSpecializer(Loop(K1.inputargs, K1.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- v4 = spec.loop.operations[-1].args[-1]
- assert spec.loop.inputargs == [K1.sum, K1.n1, K1.v]
- equaloplists(spec.loop.operations, [
- ResOperation('int_sub', [K1.v, ConstInt(1)], K1.v2),
- ResOperation('int_add', [K1.sum, K1.v], K1.sum2),
- ResOperation('int_add', [K1.sum2, K1.sum], K1.sum3),
- ResOperation('setfield_gc', [K1.n1, K1.sum], None, K1.ofs_value),
- ResOperation('escape', [K1.n1], None),
- ResOperation('getfield_gc', [K1.n1], v4, K1.ofs_value),
- ResOperation('jump', [K1.sum3, K1.n1, v4], None),
- ])
-
-
-class K:
- locals().update(A.__dict__) # :-)
- sum3 = BoxInt(3)
- v3 = BoxInt(4)
- inputargs = [sum, n1]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('getfield_gc', [n1], v3, ofs_value),
- ResOperation('int_add', [sum2, v3], sum3),
- ResOperation('jump', [sum3, n1], None),
- ]
-
-def test_K_optimize_loop():
- py.test.skip("Disabled")
- spec = CheckPerfectSpecializer(Loop(K.inputargs, K.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- assert spec.loop.inputargs == [K.sum, K.n1, K.v]
- equaloplists(spec.loop.operations, [
- ResOperation('int_sub', [K.v, ConstInt(1)], K.v2),
- ResOperation('int_add', [K.sum, K.v], K.sum2),
- ResOperation('int_add', [K.sum2, K.v], K.sum3),
- ResOperation('jump', [K.sum3, K.n1, K.v], None),
- ])
-
-# ____________________________________________________________
-
-class L:
- locals().update(A.__dict__) # :-)
- sum3 = BoxInt(3)
- v3 = BoxInt(4)
- inputargs = [sum, n1]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('escape', [n1], None),
- ResOperation('getfield_gc', [n1], v3, ofs_value),
- ResOperation('int_add', [sum2, v3], sum3),
- ResOperation('jump', [sum3, n1], None),
- ]
-
-def test_L_optimize_loop():
- py.test.skip("Disabled")
- spec = CheckPerfectSpecializer(Loop(L.inputargs, L.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- assert spec.loop.inputargs == [L.sum, L.n1, L.v]
- equaloplists(spec.loop.operations, [
- ResOperation('int_sub', [L.v, ConstInt(1)], L.v2),
- ResOperation('int_add', [L.sum, L.v], L.sum2),
- ResOperation('escape', [L.n1], None),
- ResOperation('getfield_gc', [L.n1], L.v3, L.ofs_value),
- ResOperation('int_add', [L.sum2, L.v3], L.sum3),
- ResOperation('jump', [L.sum3, L.n1, L.v3], None),
- ])
-
-# ____________________________________________________________
-
-class M:
- locals().update(A.__dict__) # :-)
- sum3 = BoxInt(3)
- v3 = BoxInt(4)
- inputargs = [sum, n1]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('escape', [n1], None),
- ResOperation('jump', [sum2, n1], None),
- ]
-
-def test_M_optimize_loop():
- py.test.skip("Disabled")
- spec = CheckPerfectSpecializer(Loop(M.inputargs, M.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- v4 = spec.loop.operations[-1].args[-1]
- assert spec.loop.inputargs == [M.sum, M.n1, M.v]
- equaloplists(spec.loop.operations, [
- ResOperation('int_sub', [M.v, ConstInt(1)], M.v2),
- ResOperation('int_add', [M.sum, M.v], M.sum2),
- ResOperation('escape', [M.n1], None),
- ResOperation('getfield_gc', [M.n1], v4, M.ofs_value),
- ResOperation('jump', [M.sum2, M.n1, v4], None),
- ])
-
-# ____________________________________________________________
-
-class N:
- locals().update(A.__dict__) # :-)
- sum3 = BoxInt(3)
- v3 = BoxInt(4)
- inputargs = [sum, n1]
- ops = [
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('getfield_gc', [n1], v, ofs_value),
- ResOperation('int_sub', [v, ConstInt(1)], v2),
- ResOperation('int_add', [sum, v], sum2),
- ResOperation('escape', [n1], None),
- ResOperation('jump', [sum2, n1], None),
- ]
-
-def test_N_optimize_loop():
- py.test.skip("Disabled")
- spec = CheckPerfectSpecializer(Loop(N.inputargs, N.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- v4 = spec.loop.operations[-1].args[-1]
- assert spec.loop.inputargs == [N.sum, N.n1, N.v]
- equaloplists(spec.loop.operations, [
- ResOperation('int_sub', [N.v, ConstInt(1)], N.v2),
- ResOperation('int_add', [N.sum, N.v], N.sum2),
- ResOperation('escape', [N.n1], None),
- ResOperation('getfield_gc', [N.n1], v4, N.ofs_value),
- ResOperation('jump', [N.sum2, N.n1, v4], None),
- ])
-
-# ____________________________________________________________
-
-class O1:
- locals().update(A.__dict__) # :-)
- inputargs = []
- ops = [
- ResOperation('escape', [], n1),
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('jump', [], None),
- ]
- set_guard(ops[-3], [])
- set_guard(ops[-2], [])
-
-def test_O1_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(O1.inputargs, O1.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- assert spec.loop.inputargs == []
- equaloplists(spec.loop.operations, [
- ResOperation('escape', [], O1.n1),
- # only the first guard_class is left
- ResOperation('guard_class', [O1.n1, ConstAddr(node_vtable, cpu)],
- None),
- ResOperation('jump', [], None),
- ])
-
-# ____________________________________________________________
-
-class O2:
- locals().update(A.__dict__) # :-)
- v1 = BoxInt(1)
- inputargs = []
- ops = [
- ResOperation('escape', [], n1),
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('oononnull', [n1], v1),
- ResOperation('guard_true', [v1], None),
- ResOperation('jump', [], None),
- ]
- set_guard(ops[-4], [])
- set_guard(ops[-2], [])
-
-def test_O2_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(O2.inputargs, O2.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- assert spec.loop.inputargs == []
- equaloplists(spec.loop.operations, [
- ResOperation('escape', [], O2.n1),
- ResOperation('guard_class', [O2.n1, ConstAddr(node_vtable, cpu)],
- None),
- # the oononnull and guard_true are gone, because we know they
- # return True -- as there was already a guard_class done on n1
- ResOperation('jump', [], None),
- ])
-
-# ____________________________________________________________
-
-class O3:
- locals().update(A.__dict__) # :-)
- v1 = BoxInt(1)
- inputargs = []
- ops = [
- ResOperation('escape', [], n1),
- ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], None),
- ResOperation('oois', [n1, ConstPtr(lltype.nullptr(llmemory.GCREF.TO))],
- v1),
- ResOperation('guard_false', [v1], None),
- ResOperation('jump', [], None),
- ]
- set_guard(ops[-4], [])
- set_guard(ops[-2], [])
-
-def test_O3_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(O3.inputargs, O3.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- assert spec.loop.inputargs == []
- equaloplists(spec.loop.operations, [
- ResOperation('escape', [], O3.n1),
- ResOperation('guard_class', [O3.n1, ConstAddr(node_vtable, cpu)],
- None),
- # the oois and guard_false are gone, because we know they
- # return False -- as there was already a guard_class done on n1
- ResOperation('jump', [], None),
- ])
-
-# ____________________________________________________________
-
-class P:
- locals().update(A.__dict__) # :-)
- thirdnode = lltype.malloc(NODE)
- n3 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, thirdnode))
- f = BoxInt(0) # False
- inputargs = [n1, n3]
- ops = [
- ResOperation('getfield_gc', [n3], v, ofs_value),
- ResOperation('setfield_gc', [n1, ConstInt(1)], None, ofs_value),
- ResOperation('getfield_gc', [n3], v2, ofs_value),
- ResOperation('int_eq', [v, v2], f),
- ResOperation('guard_false', [f], None),
- ResOperation('getfield_gc', [n1], n2, ofs_next),
- ResOperation('jump', [n2, n3], None),
- ]
- set_guard(ops[-3], [])
-
-def test_P_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(P.inputargs, P.ops))
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- # Optimization should not remove any operation.
- # If it does, then aliasing is not correctly detected.
- # It is ok to reorder just the 'getfield_gc[n1], n2' operation,
- # but the three remaining getfields/setfields *must* be in that order.
- equaloplists(spec.loop.operations, P.ops)
-
-# ____________________________________________________________
-
-class Q:
- locals().update(A.__dict__) # :-)
- inputargs = [sum]
- ops = [
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n1,
- size_of_node),
- ResOperation('setfield_gc', [n1, sum], None, ofs_value),
- ResOperation('getfield_gc', [n1], sum2, ofs_value),
- ResOperation('guard_true', [sum2], None),
- ResOperation('int_sub', [sum, ConstInt(1)], v),
- ResOperation('jump', [v], None),
- ]
- set_guard(ops[-3], [sum])
-
-def test_Q_optimize_loop():
- spec = CheckPerfectSpecializer(Loop(Q.inputargs, Q.ops), cpu=cpu)
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- equaloplists(spec.loop.operations, [
- ResOperation('guard_true', [Q.sum], None),
- ResOperation('int_sub', [Q.sum, ConstInt(1)], Q.v),
- ResOperation('jump', [Q.v], None),
- ])
-
-# ____________________________________________________________
-
-class R:
- locals().update(A.__dict__) # :-)
- inputargs = [sum]
- ops = [
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n1,
- size_of_node),
- ResOperation('int_is_true', [sum], n1nz),
- ResOperation('guard_true', [n1nz], None),
- ResOperation('new_with_vtable', [ConstAddr(node_vtable, cpu)], n2,
- size_of_node),
- ResOperation('setfield_gc', [n1, n2], None, ofs_next),
- ResOperation('int_sub', [sum, ConstInt(1)], sum2),
- ResOperation('jump', [sum2], None),
- ]
- set_guard(ops[2], [n1])
-
-def test_R_find_nodes():
- spec = CheckPerfectSpecializer(Loop(R.inputargs, R.ops), cpu=cpu)
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
-
-# ____________________________________________________________
-
-class S:
- locals().update(A.__dict__) # :-)
- n1subnode = lltype.malloc(NODE2)
- n2subnode = lltype.malloc(NODE2)
- n1sub = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, n1subnode))
- n2sub = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, n2subnode))
- inputargs = [n1sub]
- ops = [
- ResOperation('guard_class', [n1sub, ConstAddr(node2_vtable, cpu)],
- None),
- ResOperation('escape', [], n2sub),
- ResOperation('jump', [n2sub], None),
- ]
- set_guard(ops[0], [n1sub])
-
-def test_S_find_nodes():
- py.test.skip("in-progress")
- spec = CheckPerfectSpecializer(Loop(S.inputargs, S.ops), cpu=cpu)
- spec.find_nodes()
- spec.intersect_input_and_output()
- spec.optimize_loop()
- equaloplists(spec.loop.operations, S.ops)
+ perfect_specialization_finder.find_nodes(Loop(A.inputargs, A.ops))
+ nodes = perfect_specialization_finder.nodes
+ assert A.sum in nodes
+ assert A.sum2 not in nodes
+ assert nodes[A.n1] is not nodes[A.n2]
+ assert not nodes[A.n1].escaped
+ assert not nodes[A.n2].escaped
+
+ assert not nodes[A.n1].curfields
+ assert nodes[A.n1].origfields[A.ofs_value] is nodes[A.v]
+ assert not nodes[A.n2].origfields
+ assert nodes[A.n2].curfields[A.ofs_next] is nodes[A.n2]
More information about the Pypy-commit
mailing list