Author: Richard Plangger <[email protected]>
Branch: vecopt-merge
Changeset: r79092:27ddd5637fb8
Date: 2015-08-21 10:28 +0200
http://bitbucket.org/pypy/pypy/changeset/27ddd5637fb8/
Log: moved the collection of compile loop version descr to guard opt. the
assembler writes the correct offset into memory but it is not
visible in the resulting memory block (e.g. jitviewer?). something
is wrong
diff --git a/rpython/jit/backend/llgraph/runner.py
b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -265,8 +265,8 @@
self.stats = stats or MiniStats()
self.vinfo_for_tests = kwds.get('vinfo_for_tests', None)
- def stitch_bridge(self, faildescr, compiled_faildescr, jitcell_token):
- faildescr._llgraph_bridge = compiled_faildescr._llgraph_bridge
+ def stitch_bridge(self, faildescr, target):
+ faildescr._llgraph_bridge = target
def compile_loop(self, inputargs, operations, looptoken, jd_id=0,
unique_id=0, log=True, name='', logger=None):
@@ -285,6 +285,7 @@
faildescr._llgraph_bridge = lltrace
clt._llgraph_alltraces.append(lltrace)
self._record_labels(lltrace)
+ return lltrace
def _record_labels(self, lltrace):
for i, op in enumerate(lltrace.operations):
diff --git a/rpython/jit/backend/llsupport/assembler.py
b/rpython/jit/backend/llsupport/assembler.py
--- a/rpython/jit/backend/llsupport/assembler.py
+++ b/rpython/jit/backend/llsupport/assembler.py
@@ -35,7 +35,6 @@
self.exc = exc
self.is_guard_not_invalidated = is_guard_not_invalidated
self.is_guard_not_forced = is_guard_not_forced
- self.rawstart = 0
def compute_gcmap(self, gcmap, failargs, fail_locs, frame_depth):
# note that regalloc has a very similar compute, but
@@ -70,7 +69,7 @@
self.rtyper = cpu.rtyper
self._debug = False
- def stitch_bridge(self, faildescr, compiled_faildescr, token):
+ def stitch_bridge(self, faildescr, target):
raise NotImplementedError
def setup_once(self):
diff --git a/rpython/jit/backend/llsupport/llmodel.py
b/rpython/jit/backend/llsupport/llmodel.py
--- a/rpython/jit/backend/llsupport/llmodel.py
+++ b/rpython/jit/backend/llsupport/llmodel.py
@@ -97,8 +97,8 @@
inputargs, operations,
looptoken, log=log)
- def stitch_bridge(self, faildescr, compiled_faildescr, token):
- self.assembler.stitch_bridge(faildescr, compiled_faildescr, token)
+ def stitch_bridge(self, faildescr, target):
+ self.assembler.stitch_bridge(faildescr, target)
def _setup_frame_realloc(self, translate_support_code):
FUNC_TP = lltype.Ptr(lltype.FuncType([llmemory.GCREF, lltype.Signed],
diff --git a/rpython/jit/backend/x86/assembler.py
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -569,7 +569,7 @@
fullsize = self.mc.get_relative_pos()
#
rawstart = self.materialize_loop(original_loop_token)
- faildescr.rawstart = rawstart
+ faildescr.bridge_rawstart = rawstart
self.patch_stack_checks(frame_depth_no_fixed_size +
JITFRAME_FIXED_SIZE,
rawstart)
debug_bridge(descr_number, rawstart, codeendpos)
@@ -592,8 +592,9 @@
rawstart, fullsize)
return AsmInfo(ops_offset, startpos + rawstart, codeendpos - startpos)
- def stitch_bridge(self, faildescr, compiled_faildescr, token):
- self.patch_jump_for_descr(faildescr, compiled_faildescr.rawstart)
+ def stitch_bridge(self, faildescr, target):
+ assert target != 0
+ self.patch_jump_for_descr(faildescr, target)
def write_pending_failure_recoveries(self, regalloc):
# for each pending guard, generate the code of the recovery stub
@@ -604,7 +605,8 @@
regalloc.position = tok.position
tok.pos_recovery_stub = self.generate_quick_failure(tok,
regalloc)
else:
- self.store_info_on_descr(0, tok)
+ startpos = self.mc.get_relative_pos()
+ self.store_info_on_descr(startpos, tok)
if WORD == 8 and len(self.pending_memoryerror_trampoline_from) > 0:
self.error_trampoline_64 = self.generate_propagate_error_64()
diff --git a/rpython/jit/backend/x86/regalloc.py
b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -322,7 +322,6 @@
if accum:
loc = self.loc(accum.getoriginalbox())
faillocs.append(loc)
- import pdb; pdb.set_trace()
self.update_accumulation_loc(arg, accum, descr, i)
else:
faillocs.append(self.loc(arg))
diff --git a/rpython/jit/metainterp/compile.py
b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -192,6 +192,8 @@
metainterp_sd = metainterp.staticdata
cpu = metainterp_sd.cpu
if loop.versions is not None:
+ # compile each version once for the first fail descr!
+ # this assumes that the root trace (= loop) is already compiled
for version in loop.versions:
if len(version.faildescrs) == 0:
continue
@@ -200,12 +202,16 @@
vl.inputargs = version.inputargs
vl.operations = version.operations
vl.original_jitcell_token = jitcell_token
- send_bridge_to_backend(jitdriver_sd, metainterp_sd,
- faildescr, version.inputargs,
- version.operations, jitcell_token)
+ asminfo = send_bridge_to_backend(jitdriver_sd, metainterp_sd,
+ faildescr, version.inputargs,
+ version.operations, jitcell_token)
record_loop_or_bridge(metainterp_sd, vl)
- for fd in version.faildescrs[1:]:
- cpu.stitch_bridge(fd, faildescr, jitcell_token)
+ version.compiled = faildescr.bridge_rawstart
+ assert asminfo is not None
+ # stitch the rest of the traces
+ for version in loop.versions:
+ for faildescr in version.faildescrs[1:]:
+ cpu.stitch_bridge(faildescr, version.compiled)
loop.versions = None
def compile_retrace(metainterp, greenkey, start,
@@ -437,6 +443,7 @@
#if metainterp_sd.warmrunnerdesc is not None: # for tests
# metainterp_sd.warmrunnerdesc.memory_manager.keep_loop_alive(
# original_loop_token)
+ return asminfo
# ____________________________________________________________
@@ -742,6 +749,11 @@
def loop_version(self):
return True
+ def clone(self):
+ cloned = ResumeGuardDescr.clone(self)
+ cloned.version = self.version
+ return cloned
+
class AllVirtuals:
llopaque = True
cache = None
diff --git a/rpython/jit/metainterp/history.py
b/rpython/jit/metainterp/history.py
--- a/rpython/jit/metainterp/history.py
+++ b/rpython/jit/metainterp/history.py
@@ -758,38 +758,7 @@
label = operations[idx]
self.label_pos = idx
self.inputargs = label.getarglist()
-
- def register_all_guards(self, opt_ops, invariant_arg_count=0):
- from rpython.jit.metainterp.compile import CompileLoopVersionDescr
- pass_by = 0
- idx = index_of_first(rop.LABEL, opt_ops)
- if opt_ops[idx].getdescr() is not opt_ops[-1].getdescr():
- idx = index_of_first(rop.LABEL, opt_ops, pass_by=1)
- assert idx >= 0
- version_failargs = opt_ops[idx].getarglist()
- if invariant_arg_count > 0:
- # constant/variable expansion append arguments to the label
- # if they are not removed, the register allocator cannot
- # reconstruct the binding if len(inputargs) != len(faillocs)
- to = len(version_failargs) - invariant_arg_count
- assert to >= 0
- version_failargs = version_failargs[:to]
-
- for op in opt_ops:
- if op.is_guard():
- assert isinstance(op, GuardResOp)
- descr = op.getdescr()
- if descr.loop_version():
- assert isinstance(descr, CompileLoopVersionDescr)
- if descr.version is None:
- # currently there is only ONE versioning,
- # that is the original loop after unrolling.
- # if there are more possibilites, let the descr
- # know which loop version he preferes
- descr.version = self
- self.faildescrs.append(descr)
- op.setfailargs(version_failargs)
- op.rd_snapshot = None
+ self.compiled = None
def register_guard(self, op):
from rpython.jit.metainterp.compile import CompileLoopVersionDescr
@@ -798,8 +767,6 @@
assert isinstance(descr, CompileLoopVersionDescr)
descr.version = self
self.faildescrs.append(descr)
- op.setfailargs(self.inputargs)
- op.rd_snapshot = None
def update_token(self, jitcell_token, all_target_tokens):
# this is only invoked for versioned loops!
@@ -892,16 +859,22 @@
return self.operations
def find_first_index(self, opnum, pass_by=0):
- """ return the first operation having the same opnum or -1 """
+ """ return the first index of the operation having the same opnum or
-1 """
return index_of_first(opnum, self.operations, pass_by)
+ def find_first(self, opnum, pass_by=0):
+ index = self.find_first_index(opnum, pass_by)
+ if index != -1:
+ return self.operations[index]
+ return None
+
def snapshot(self):
version = LoopVersion(self.copy_operations())
self.versions.append(version)
return version
def copy_operations(self):
- from rpython.jit.metainterp.compile import ResumeGuardDescr
+ from rpython.jit.metainterp.compile import ResumeGuardDescr,
CompileLoopVersionDescr
ignore = (rop.DEBUG_MERGE_POINT,)
operations = []
for op in self.operations:
@@ -913,6 +886,8 @@
if cloned.is_guard() and descr:
assert isinstance(descr, ResumeGuardDescr)
cloned.setdescr(descr.clone())
+ if isinstance(descr, CompileLoopVersionDescr):
+ descr.version.register_guard(cloned)
return operations
def get_display_text(self): # for graphpage.py
diff --git a/rpython/jit/metainterp/logger.py b/rpython/jit/metainterp/logger.py
--- a/rpython/jit/metainterp/logger.py
+++ b/rpython/jit/metainterp/logger.py
@@ -102,6 +102,7 @@
return descr.repr_of_descr()
def repr_of_arg(self, arg):
+ return str(arg) # XXX
try:
mv = self.memo[arg]
except KeyError:
diff --git a/rpython/jit/metainterp/optimizeopt/guard.py
b/rpython/jit/metainterp/optimizeopt/guard.py
--- a/rpython/jit/metainterp/optimizeopt/guard.py
+++ b/rpython/jit/metainterp/optimizeopt/guard.py
@@ -10,7 +10,7 @@
from rpython.jit.metainterp.resoperation import (rop, ResOperation, GuardResOp)
from rpython.jit.metainterp.history import (ConstInt, BoxVector,
BoxFloat, BoxInt, ConstFloat, Box, Const)
-from rpython.jit.metainterp.compile import ResumeGuardDescr
+from rpython.jit.metainterp.compile import ResumeGuardDescr,
CompileLoopVersionDescr
from rpython.rlib.objectmodel import we_are_translated
class Guard(object):
@@ -70,7 +70,7 @@
return (lc <= 0 and rc >= 0)
return False
- def transitive_imply(self, other, opt):
+ def transitive_imply(self, other, opt, loop):
if self.op.getopnum() != other.op.getopnum():
# stronger restriction, intermixing e.g. <= and < would be possible
return None
@@ -91,6 +91,8 @@
assert isinstance(descr, ResumeGuardDescr)
guard.setdescr(descr.clone())
guard.setarg(0, box_result)
+ label = loop.find_first(rop.LABEL)
+ guard.setfailargs(label.getarglist())
opt.emit_operation(guard)
return guard
@@ -149,6 +151,10 @@
def set_to_none(self, operations):
assert operations[self.index] is self.op
operations[self.index] = None
+ descr = self.op.getdescr()
+ if isinstance(descr, CompileLoopVersionDescr) and descr.version:
+ descr.version.faildescrs.remove(descr)
+ descr.version = None
if operations[self.index-1] is self.cmp_op:
operations[self.index-1] = None
@@ -171,12 +177,14 @@
return Guard(index, guard_op, cmp_op, index_vars)
class GuardStrengthenOpt(object):
- def __init__(self, index_vars):
+ """ Note that this optimization is only used in the vector optimizer (yet)
"""
+ def __init__(self, index_vars, has_two_labels):
self.index_vars = index_vars
self._newoperations = []
self.strength_reduced = 0 # how many guards could be removed?
self.strongest_guards = {}
self.guards = {}
+ self.has_two_labels = has_two_labels
def collect_guard_information(self, loop):
operations = loop.operations
@@ -256,8 +264,18 @@
# the guards are ordered. guards[i] is before guards[j] iff i < j
self.collect_guard_information(loop)
self.eliminate_guards(loop)
+ #
+ assert len(loop.versions) == 1, "none or more than one version created"
+ version = loop.versions[0]
- if user_code or True:
+ for op in loop.operations:
+ if not op.is_guard():
+ continue
+ descr = op.getdescr()
+ if isinstance(descr, CompileLoopVersionDescr):
+ version.register_guard(op)
+
+ if user_code and False:
version = loop.snapshot()
self.eliminate_array_bound_checks(loop, version)
@@ -278,11 +296,16 @@
# iff we add invariant guards
one = guards[0]
for other in guards[1:]:
- transitive_guard = one.transitive_imply(other, self)
+ transitive_guard = one.transitive_imply(other, self, loop)
if transitive_guard:
other.set_to_none(loop.operations)
version.register_guard(transitive_guard)
- loop.operations = self._newoperations + \
- [op for op in loop.operations if op]
+ if self.has_two_labels:
+ oplist = [loop.operations[0]] + self._newoperations + \
+ [op for op in loop.operations[1:] if op]
+ loop.operations = oplist
+ else:
+ loop.operations = self._newoperations + \
+ [op for op in loop.operations if op]
diff --git a/rpython/jit/metainterp/optimizeopt/schedule.py
b/rpython/jit/metainterp/optimizeopt/schedule.py
--- a/rpython/jit/metainterp/optimizeopt/schedule.py
+++ b/rpython/jit/metainterp/optimizeopt/schedule.py
@@ -856,34 +856,6 @@
assert not isinstance(box, BoxVector)
self.box_to_vbox[box] = (off, vector)
- def prepend_invariant_operations(self, oplist, orig_label_args):
- if len(self.invariant_oplist) > 0:
- label = oplist[0]
- assert label.getopnum() == rop.LABEL
- #
- jump = oplist[-1]
- assert jump.getopnum() == rop.JUMP
- #
- label_args = label.getarglist()[:]
- jump_args = jump.getarglist()
- for var in self.invariant_vector_vars:
- label_args.append(var)
- jump_args.append(var)
- #
- # in case of any invariant_vector_vars, the label is restored
- # and the invariant operations are added between the original label
- # and the new label
- descr = label.getdescr()
- assert isinstance(descr, TargetToken)
- token = TargetToken(descr.targeting_jitcell_token)
- oplist[0] = label.copy_and_change(label.getopnum(),
args=label_args, descr=token)
- oplist[-1] = jump.copy_and_change(jump.getopnum(), args=jump_args,
descr=token)
- #
- return [ResOperation(rop.LABEL, orig_label_args, None, descr)] + \
- self.invariant_oplist + oplist
- #
- return oplist
-
class Pack(object):
""" A pack is a set of n statements that are:
* isomorphic
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_guard.py
b/rpython/jit/metainterp/optimizeopt/test/test_guard.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_guard.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_guard.py
@@ -84,7 +84,7 @@
if op.is_guard():
op.setdescr(compile.CompileLoopVersionDescr())
dep = DependencyGraph(loop)
- opt = GuardStrengthenOpt(dep.index_vars)
+ opt = GuardStrengthenOpt(dep.index_vars, False)
opt.propagate_all_forward(loop, user_code)
return opt
diff --git a/rpython/jit/metainterp/optimizeopt/vectorize.py
b/rpython/jit/metainterp/optimizeopt/vectorize.py
--- a/rpython/jit/metainterp/optimizeopt/vectorize.py
+++ b/rpython/jit/metainterp/optimizeopt/vectorize.py
@@ -49,10 +49,11 @@
#
opt = VectorizingOptimizer(metainterp_sd, jitdriver_sd, loop, 0)
opt.propagate_all_forward()
- gso = GuardStrengthenOpt(opt.dependency_graph.index_vars)
+ #
+ gso = GuardStrengthenOpt(opt.dependency_graph.index_vars,
opt.has_two_labels)
gso.propagate_all_forward(opt.loop, user_code)
# connect all compile loop version fail descriptors to this version
- version.register_all_guards(loop.operations, opt.appended_arg_count)
+ #version.register_all_guards(loop.operations, opt.appended_arg_count)
#
#
end = time.clock()
@@ -135,6 +136,7 @@
self.costmodel = X86_CostModel(cost_threshold,
self.cpu.vector_register_size)
self.appended_arg_count = 0
self.orig_label_args = None
+ self.has_two_labels = False
def propagate_all_forward(self, clear=True):
self.clear_newoperations()
@@ -503,11 +505,46 @@
accum = arg.getaccum()
if accum:
accum.save_to_descr(op.getdescr(),i)
- self.loop.operations = \
- sched_data.prepend_invariant_operations(self._newoperations,
- self.orig_label_args)
+ self.has_two_labels = len(sched_data.invariant_oplist) > 0
+ self.loop.operations =
self.prepend_invariant_operations(sched_data)
+ else:
+ self.loop.operations = self._newoperations
+
self.clear_newoperations()
+ def prepend_invariant_operations(self, sched_data):
+ """ Add invariant operations to the trace loop. returns the operation
list
+ as first argument and a second a boolean value. it is true if any
inva
+ """
+ oplist = self._newoperations
+
+ if len(sched_data.invariant_oplist) > 0:
+ label = oplist[0]
+ assert label.getopnum() == rop.LABEL
+ #
+ jump = oplist[-1]
+ assert jump.getopnum() == rop.JUMP
+ #
+ label_args = label.getarglist()[:]
+ jump_args = jump.getarglist()
+ for var in sched_data.invariant_vector_vars:
+ label_args.append(var)
+ jump_args.append(var)
+ #
+ # in case of any invariant_vector_vars, the label is restored
+ # and the invariant operations are added between the original label
+ # and the new label
+ descr = label.getdescr()
+ assert isinstance(descr, TargetToken)
+ token = TargetToken(descr.targeting_jitcell_token)
+ oplist[0] = label.copy_and_change(label.getopnum(),
args=label_args, descr=token)
+ oplist[-1] = jump.copy_and_change(jump.getopnum(), args=jump_args,
descr=token)
+ #
+ return [ResOperation(rop.LABEL, self.orig_label_args, None,
descr)] + \
+ sched_data.invariant_oplist + oplist
+ #
+ return oplist
+
def analyse_index_calculations(self):
ee_pos = self.loop.find_first_index(rop.GUARD_EARLY_EXIT)
if len(self.loop.operations) <= 2 or ee_pos == -1:
@@ -580,7 +617,6 @@
descr.copy_all_attributes_from(olddescr)
#
tgt_op.setdescr(descr)
- tgt_op.rd_snapshot = op.rd_snapshot
tgt_op.setfailargs(op.getfailargs()[:])
diff --git a/rpython/jit/metainterp/test/test_vectorize.py
b/rpython/jit/metainterp/test/test_vectorize.py
--- a/rpython/jit/metainterp/test/test_vectorize.py
+++ b/rpython/jit/metainterp/test/test_vectorize.py
@@ -222,17 +222,19 @@
def test_accum(self):
myjitdriver = JitDriver(greens = [], reds = 'auto')
- T = lltype.Array(rffi.DOUBLE, hints={'nolength': True})
+ T = lltype.Array(rffi.DOUBLE)
def f(d, value):
va = lltype.malloc(T, d, flavor='raw', zero=True)
for i in range(d):
va[i] = value
r = 0
i = 0
+ k = d + 2
+ # in this case a guard k <= d is inserted which fails right away!
while i < d:
myjitdriver.jit_merge_point()
- if not(i < d):
- raise IndexError
+ #if not(i < k):
+ # k -= 1
r += va[i]
i += 1
lltype.free(va, flavor='raw')
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit