Author: Richard Plangger <[email protected]>
Branch: vecopt2
Changeset: r77120:0a2d06280172
Date: 2015-04-20 09:33 +0200
http://bitbucket.org/pypy/pypy/changeset/0a2d06280172/
Log: renamed guard_no_early_exit to guard_early_exit started modify the
register allocator and the code generation to support the new boxes
and instructions added a vectorize test in the backend for x86
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
@@ -855,8 +855,7 @@
argboxes = self.current_op.getarglist()
self.do_renaming(argboxes, args)
- def execute_guard_no_early_exit(self, descr):
- # TODO
+ def execute_guard_early_exit(self, descr):
pass
def execute_guard_true(self, descr, arg):
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
@@ -2414,6 +2414,16 @@
self.save_into_mem(addr, imm0, imm(current))
i += current
+ # vector operations
+ def genop_vec_raw_load(self, op, arglocs, resloc):
+ base_loc, ofs_loc, size_loc, ofs, sign_loc = arglocs
+ assert isinstance(ofs, ImmedLoc)
+ assert isinstance(size_loc, ImmedLoc)
+ scale = get_scale(size_loc.value)
+ src_addr = addr_add(base_loc, ofs_loc, ofs.value, scale)
+ assert False
+ #self.load_from_mem(resloc, src_addr, size_loc, sign_loc)
+
genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST
genop_list = [Assembler386.not_implemented_op] * rop._LAST
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
@@ -22,7 +22,7 @@
from rpython.jit.codewriter import longlong
from rpython.jit.codewriter.effectinfo import EffectInfo
from rpython.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr,
- ConstFloat, BoxInt, BoxFloat, INT, REF, FLOAT, TargetToken)
+ ConstFloat, BoxInt, BoxFloat, INT, REF, FLOAT, VECTOR, TargetToken)
from rpython.jit.metainterp.resoperation import rop, ResOperation
from rpython.rlib import rgc
from rpython.rlib.objectmodel import we_are_translated
@@ -61,7 +61,7 @@
class X86XMMRegisterManager(RegisterManager):
- box_types = [FLOAT]
+ box_types = [FLOAT, VECTOR]
all_regs = [xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7]
# we never need lower byte I hope
save_around_call_regs = all_regs
@@ -208,7 +208,7 @@
def force_allocate_reg(self, var, forbidden_vars=[], selected_reg=None,
need_lower_byte=False):
- if var.type == FLOAT:
+ if var.type == FLOAT or var.type == VECTOR:
return self.xrm.force_allocate_reg(var, forbidden_vars,
selected_reg, need_lower_byte)
else:
@@ -1457,6 +1457,23 @@
self.rm.possibly_free_var(length_box)
self.rm.possibly_free_var(dstaddr_box)
+ # vector operations
+ def consider_vec_raw_load(self, op):
+ itemsize, ofs, sign = unpack_arraydescr(op.getdescr())
+ args = op.getarglist()
+ base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args)
+ ofs_loc = self.rm.make_sure_var_in_reg(op.getarg(1), args)
+ result_loc = self.force_allocate_reg(op.result)
+ if sign:
+ sign_loc = imm1
+ else:
+ sign_loc = imm0
+ self.perform(op, [base_loc, ofs_loc, imm(itemsize), imm(ofs),
+ sign_loc], result_loc)
+
+ def consider_guard_early_exit(self, op):
+ pass
+
def not_implemented_op(self, op):
not_implemented("not implemented operation: %s" % op.getopname())
diff --git a/rpython/jit/backend/x86/test/test_vectorize.py
b/rpython/jit/backend/x86/test/test_vectorize.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/x86/test/test_vectorize.py
@@ -0,0 +1,12 @@
+import py
+from rpython.jit.backend.detect_cpu import getcpuclass
+from rpython.jit.metainterp.warmspot import ll_meta_interp
+from rpython.jit.metainterp.test import support, test_vectorize
+from rpython.jit.backend.x86.test import test_basic
+from rpython.rlib.jit import JitDriver
+
+
+class TestBasic(test_basic.Jit386Mixin, test_vectorize.VectorizeLLtypeTests):
+ # for the individual tests see
+ # ====> ../../../metainterp/test/test_basic.py
+ pass
diff --git a/rpython/jit/metainterp/blackhole.py
b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -1482,9 +1482,8 @@
#
if opnum == rop.GUARD_FUTURE_CONDITION:
pass
- elif opnum == rop.GUARD_NO_EARLY_EXIT:
+ elif opnum == rop.GUARD_EARLY_EXIT:
self.position = resumedescr.rd_frame_info_list.pc
- pass
elif opnum == rop.GUARD_TRUE:
# Produced directly by some goto_if_not_xxx() opcode that did not
# jump, but which must now jump. The pc is just after the opcode.
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
@@ -685,8 +685,8 @@
class ResumeAtPositionDescr(ResumeGuardDescr):
guard_opnum = rop.GUARD_FUTURE_CONDITION
-class ResumeAtEarylExitDescr(ResumeGuardDescr):
- guard_opnum = rop.GUARD_NO_EARLY_EXIT
+class ResumeAtLoopHeaderDescr(ResumeGuardDescr):
+ guard_opnum = rop.GUARD_EARLY_EXIT
class AllVirtuals:
llopaque = True
@@ -775,8 +775,8 @@
resumedescr = ResumeGuardNotInvalidated()
elif opnum == rop.GUARD_FUTURE_CONDITION:
resumedescr = ResumeAtPositionDescr()
- elif opnum == rop.GUARD_NO_EARLY_EXIT:
- resumedescr = ResumeAtEarylExitDescr()
+ elif opnum == rop.GUARD_EARLY_EXIT:
+ resumedescr = ResumeAtLoopHeaderDescr()
elif opnum == rop.GUARD_VALUE:
resumedescr = ResumeGuardValueDescr()
elif opnum == rop.GUARD_NONNULL:
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
@@ -927,6 +927,8 @@
insns = {}
for loop in self.get_all_loops():
insns = loop.summary(adding_insns=insns, omit_finish=omit_finish)
+ if 'guard_early_exit' in insns: # XXX
+ del insns['guard_early_exit']
return self._check_insns(insns, expected, check)
def _check_insns(self, insns, expected, check):
diff --git a/rpython/jit/metainterp/optimizeopt/dependency.py
b/rpython/jit/metainterp/optimizeopt/dependency.py
--- a/rpython/jit/metainterp/optimizeopt/dependency.py
+++ b/rpython/jit/metainterp/optimizeopt/dependency.py
@@ -1,6 +1,6 @@
import py
-from rpython.jit.metainterp.compile import ResumeAtEarylExitDescr
+from rpython.jit.metainterp import compile
from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
from rpython.jit.metainterp.resoperation import rop
from rpython.jit.codewriter.effectinfo import EffectInfo
@@ -105,13 +105,17 @@
def relax_guard_to(self, guard):
""" Relaxes a guard operation to an earlier guard. """
assert self.op.is_guard()
- assert guard.op.is_guard()
+ assert guard.is_guard()
- my_op = self.getoperation()
- op = guard.getoperation()
- my_op.setdescr(ResumeAtEarylExitDescr())
- my_op.setfailargs(op.getfailargs())
- my_op.rd_snapshot = op.rd_snapshot
+ tgt_op = self.getoperation()
+ op = guard
+ #descr = compile.ResumeAtLoopHeaderDescr()
+ descr = compile.ResumeAtLoopHeaderDescr()
+ tgt_op.setdescr(descr)
+ if not we_are_translated():
+ tgt_op.setfailargs(op.getfailargs())
+ tgt_op.rd_snapshot = op.rd_snapshot
+ tgt_op.rd_frame_info_list = op.rd_frame_info_list
def edge_to(self, to, arg=None, label=None):
assert self != to
@@ -138,7 +142,7 @@
self.adjacent_list_back = []
def is_guard_early_exit(self):
- return self.op.getopnum() == rop.GUARD_NO_EARLY_EXIT
+ return self.op.getopnum() == rop.GUARD_EARLY_EXIT
def loads_from_complex_object(self):
return rop._ALWAYS_PURE_LAST <= self.op.getopnum() <= rop._MALLOC_FIRST
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py
b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -797,7 +797,7 @@
if op.getdescr() is not None:
descr = op.getdescr()
assert isinstance(descr, compile.ResumeAtPositionDescr) or \
- isinstance(descr, compile.ResumeAtEarylExitDescr)
+ isinstance(descr, compile.ResumeAtLoopHeaderDescr)
else:
descr = compile.invent_fail_descr_for_op(op.getopnum(), self)
diff --git a/rpython/jit/metainterp/optimizeopt/simplify.py
b/rpython/jit/metainterp/optimizeopt/simplify.py
--- a/rpython/jit/metainterp/optimizeopt/simplify.py
+++ b/rpython/jit/metainterp/optimizeopt/simplify.py
@@ -65,8 +65,8 @@
def optimize_GUARD_FUTURE_CONDITION(self, op):
pass
- def optimize_GUARD_NO_EARLY_EXIT(self, op):
- pass
+ #def optimize_GUARD_EARLY_EXIT(self, op):
+ # pass
dispatch_opt = make_dispatcher_method(OptSimplify, 'optimize_',
default=OptSimplify.emit_operation)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py
b/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py
@@ -186,13 +186,11 @@
it is unrolled 16 times. (it is the smallest type in the trace) """
ops = """
[p0,i0]
- guard_no_early_exit() []
raw_load(p0,i0,descr=chararraydescr)
jump(p0,i0)
"""
opt_ops = """
[p0,i0]
- guard_no_early_exit() []
{}
jump(p0,i0)
""".format(('\n' + ' '
*8).join(['raw_load(p0,i0,descr=chararraydescr)'] * 16))
@@ -672,7 +670,7 @@
def test_packset_extend_load_modify_store(self):
ops = """
[p0,i0]
- guard_no_early_exit() []
+ guard_early_exit() []
i1 = int_add(i0, 1)
i2 = int_le(i1, 16)
guard_true(i2) [p0, i0]
@@ -823,7 +821,7 @@
def test_schedule_vector_operation(self, op, descr, stride):
ops = """
[p0,p1,p2,i0] # 0
- guard_no_early_exit() []
+ guard_early_exit() []
i10 = int_le(i0, 128) # 1, 8, 15, 22
guard_true(i10) [p0,p1,p2,i0] # 2, 9, 16, 23
i2 = getarrayitem_raw(p0, i0, descr={descr}arraydescr) # 3, 10, 17, 24
@@ -841,7 +839,6 @@
i11 = int_le(i1, 128)
guard_true(i11) []
i12 = int_add(i1, {stride})
- guard_no_early_exit() []
v1 = vec_getarrayitem_raw(p0, i0, 2, descr={descr}arraydescr)
v2 = vec_getarrayitem_raw(p1, i0, 2, descr={descr}arraydescr)
v3 = {op}(v1,v2,2)
@@ -876,7 +873,7 @@
pytest.skip("")
ops = """
[i0, i1, i2, i3, i4, i5, i6, i7]
- guard_no_early_exit() []
+ guard_early_exit() []
i9 = int_mul(i0, 8)
i10 = raw_load(i3, i9, descr=intarraydescr)
i11 = int_mul(i0, 8)
@@ -895,7 +892,7 @@
def test_vschedule_trace_1(self):
ops = """
[i0, i1, i2, i3, i4]
- guard_no_early_exit() []
+ guard_early_exit() []
i6 = int_mul(i0, 8)
i7 = raw_load(i2, i6, descr=intarraydescr)
i8 = raw_load(i3, i6, descr=intarraydescr)
@@ -915,7 +912,6 @@
i13 = int_add(i11, 1)
i18 = int_lt(i13, i1)
guard_true(i18) []
- guard_no_early_exit() []
i6 = int_mul(i0, 8)
v19 = vec_raw_load(i2, i6, 2, descr=intarraydescr)
v20 = vec_raw_load(i3, i6, 2, descr=intarraydescr)
@@ -930,7 +926,7 @@
pytest.skip()
ops = """
[i0, i1, i2, i3, i4, i5, i6, i7]
- guard_no_early_exit() []
+ guard_early_exit() []
i8 = raw_load(i3, i0, descr=intarraydescr)
i9 = raw_load(i4, i0, descr=intarraydescr)
i10 = int_add(i8, i9)
@@ -952,7 +948,6 @@
i16 = int_add(i12, 8)
i21 = int_lt(i16, i20)
guard_true(i21) []
- guard_no_early_exit() []
v22 = vec_raw_load(i3, i0, 2, descr=intarraydescr)
v23 = vec_raw_load(i4, i0, 2, descr=intarraydescr)
v24 = vec_int_add(v22, v23)
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
@@ -1,5 +1,6 @@
import sys
import py
+from rpython.jit.metainterp.compile import ResumeAtLoopHeaderDescr
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.jit.metainterp.history import (ConstInt, VECTOR, BoxVector,
TargetToken, JitCellToken)
@@ -64,6 +65,8 @@
self.packset = None
self.unroll_count = 0
self.smallest_type_bytes = 0
+ self.early_exit = None
+ self.future_condition = None
def propagate_all_forward(self):
self.clear_newoperations()
@@ -95,6 +98,8 @@
self.schedule()
def emit_operation(self, op):
+ if op.getopnum() == rop.GUARD_EARLY_EXIT:
+ return
self._last_emitted_op = op
self._newoperations.append(op)
@@ -115,19 +120,18 @@
assert label_op.getopnum() == rop.LABEL
assert jump_op.is_final()
- # XXX self.vec_info.track_memory_refs = True
-
self.emit_unrolled_operation(label_op)
-
- # TODO use the new optimizer structure (branch of fijal)
- #label_op_args = [self.getvalue(box).get_key_box() for box in
label_op.getarglist()]
- #values = [self.getvalue(box) for box in label_op.getarglist()]
+ #guard_ee_op = ResOperation(rop.GUARD_EARLY_EXIT, [], None,
ResumeAtLoopHeaderDescr())
+ #guard_ee_op.rd_snapshot = Snapshot(None, loop.inputargs[:])
+ #self.emit_unrolled_operation(guard_ee_op)
operations = []
for i in range(1,op_count-1):
+ op = loop.operations[i].clone()
if loop.operations[i].getopnum() == rop.GUARD_FUTURE_CONDITION:
- continue
- op = loop.operations[i].clone()
+ pass
+ if loop.operations[i].getopnum() == rop.GUARD_EARLY_EXIT:
+ self.future_condition = op
operations.append(op)
self.emit_unrolled_operation(op)
@@ -146,7 +150,9 @@
rename_map[la] = ja
#
for op in operations:
- if op.getopnum() in (rop.GUARD_NO_EARLY_EXIT,
rop.GUARD_FUTURE_CONDITION):
+ if op.getopnum() == rop.GUARD_FUTURE_CONDITION:
+ continue # do not unroll this operation twice
+ if op.getopnum() == rop.GUARD_EARLY_EXIT:
continue # do not unroll this operation twice
copied_op = op.clone()
if copied_op.result is not None:
@@ -359,9 +365,11 @@
early_exit_idx = 1
label = self.dependency_graph.getnode(label_idx)
ee_guard = self.dependency_graph.getnode(early_exit_idx)
- if not ee_guard.getopnum() == rop.GUARD_NO_EARLY_EXIT:
+ if not ee_guard.is_guard_early_exit():
return # cannot relax
+ #self.early_exit = ee_guard
+
for guard_node in self.dependency_graph.guards:
if guard_node == ee_guard:
continue
@@ -391,7 +399,7 @@
guard_node.edge_to(ee_guard, label='pullup')
label.remove_edge_to(ee_guard)
- guard_node.relax_guard_to(ee_guard)
+ guard_node.relax_guard_to(self.future_condition)
def must_unpack_result_to_exec(op, target_op):
# TODO either move to resop or util
diff --git a/rpython/jit/metainterp/pyjitpl.py
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -2133,7 +2133,10 @@
self.resumekey = compile.ResumeFromInterpDescr(original_greenkey)
self.history.inputargs = original_boxes[num_green_args:]
self.seen_loop_header_for_jdindex = -1
- self.generate_guard(rop.GUARD_NO_EARLY_EXIT)
+ # can only emit early exit if liveness is present
+ # TODO think of a better way later
+ if self.framestack[-1].jitcode.liveness.get(0):
+ self.generate_guard(rop.GUARD_EARLY_EXIT)
try:
self.interpret()
except SwitchToBlackhole, stb:
diff --git a/rpython/jit/metainterp/resoperation.py
b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -418,7 +418,7 @@
'GUARD_NOT_FORCED/0d', # may be called with an exception currently set
'GUARD_NOT_FORCED_2/0d', # same as GUARD_NOT_FORCED, but for finish()
'GUARD_NOT_INVALIDATED/0d',
- 'GUARD_NO_EARLY_EXIT/0d', # is removable, may be patched by an optimization
+ 'GUARD_EARLY_EXIT/0d',
'GUARD_FUTURE_CONDITION/0d', # is removable, may be patched by an
optimization
'_GUARD_LAST', # ----- end of guard operations -----
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
@@ -12,7 +12,7 @@
from rpython.rlib.rawstorage import (alloc_raw_storage, raw_storage_setitem,
free_raw_storage, raw_storage_getitem)
-class VectorizeTests(object):
+class VectorizeTests:
enable_opts = 'all'
def meta_interp(self, f, args, policy=None):
@@ -115,5 +115,8 @@
if i > 4:
self.check_trace_count(1)
-class TestLLtype(VectorizeTests, LLJitMixin):
+class VectorizeLLtypeTests(VectorizeTests):
pass
+
+class TestLLtype(VectorizeLLtypeTests, LLJitMixin):
+ pass
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit