Author: Armin Rigo <ar...@tunes.org>
Branch: conditional_call_value_2
Changeset: r86996:87c41fa2e0f5
Date: 2016-09-11 12:23 +0200
http://bitbucket.org/pypy/pypy/changeset/87c41fa2e0f5/

Log:    Add support for COND_CALL_X in the x86 backend

diff --git a/rpython/jit/backend/llsupport/regalloc.py 
b/rpython/jit/backend/llsupport/regalloc.py
--- a/rpython/jit/backend/llsupport/regalloc.py
+++ b/rpython/jit/backend/llsupport/regalloc.py
@@ -757,17 +757,17 @@
         next_op = operations[i + 1]
         opnum = next_op.getopnum()
         if (opnum != rop.GUARD_TRUE and opnum != rop.GUARD_FALSE
-                                    and opnum != rop.COND_CALL):
+                                    and opnum != rop.COND_CALL_N):
             return False
         if next_op.getarg(0) is not op:
             return False
         if self.longevity[op][1] > i + 1:
             return False
-        if opnum != rop.COND_CALL:
+        if opnum != rop.COND_CALL_N:
             if op in operations[i + 1].getfailargs():
                 return False
         else:
-            if op in operations[i + 1].getarglist()[1:]:
+            if op in operations[i + 1].getarglist()[3:]:
                 return False
         return True
 
diff --git a/rpython/jit/backend/llsupport/rewrite.py 
b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -392,7 +392,7 @@
         opnum = next_op.getopnum()
         if not (opnum == rop.GUARD_TRUE or
                 opnum == rop.GUARD_FALSE or
-                opnum == rop.COND_CALL):
+                opnum == rop.COND_CALL_N):
             return False
         if next_op.getarg(0) is not op:
             return False
diff --git a/rpython/jit/backend/test/runner_test.py 
b/rpython/jit/backend/test/runner_test.py
--- a/rpython/jit/backend/test/runner_test.py
+++ b/rpython/jit/backend/test/runner_test.py
@@ -2215,51 +2215,6 @@
         excvalue = self.cpu.grab_exc_value(deadframe)
         assert not excvalue
 
-    def test_cond_call_value(self):
-        def func_int(*args):
-            called.append(args)
-            return len(args) * 100 + 1000
-
-        for i in range(5):
-            called = []
-
-            FUNC = self.FuncType([lltype.Signed] * i, lltype.Signed)
-            func_ptr = llhelper(lltype.Ptr(FUNC), func_int)
-            calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                                             EffectInfo.MOST_GENERAL)
-
-            ops = '''
-            [i0, i1, i2, i3, i4, i5, i6, f0, f1]
-            i15 = cond_call_i(i1, 20, ConstClass(func_ptr), %s)
-            guard_false(i0, descr=faildescr) [i1,i2,i3,i4,i5,i6,i15, f0,f1]
-            finish(i15)
-            ''' % ', '.join(['i%d' % (j + 2) for j in range(i)] +
-                            ["descr=calldescr"])
-            loop = parse(ops, namespace={'faildescr': BasicFailDescr(),
-                                         'func_ptr': func_ptr,
-                                         'calldescr': calldescr})
-            looptoken = JitCellToken()
-            self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
-            f1 = longlong.getfloatstorage(1.2)
-            f2 = longlong.getfloatstorage(3.4)
-            frame = self.cpu.execute_token(looptoken, 1, 50, 1, 2, 3, 4, 5,
-                                           f1, f2)
-            assert not called
-            assert [self.cpu.get_int_value(frame, j) for j in range(7)] == [
-                        50, 1, 2, 3, 4, 5, 50]
-            assert longlong.getrealfloat(
-                        self.cpu.get_float_value(frame, 7)) == 1.2
-            assert longlong.getrealfloat(
-                        self.cpu.get_float_value(frame, 8)) == 3.4
-            #
-            frame = self.cpu.execute_token(looptoken, 1, 20, 1, 2, 3, 4, 5,
-                                           f1, f2)
-            assert called == [(1, 2, 3, 4)[:i]]
-            assert [self.cpu.get_int_value(frame, j) for j in range(7)] == [
-                        20, 1, 2, 3, 4, 5, i * 100 + 1000]
-            assert longlong.getrealfloat(self.cpu.get_float_value(frame, 7)) 
== 1.2
-            assert longlong.getrealfloat(self.cpu.get_float_value(frame, 8)) 
== 3.4
-
     def test_cond_call_gc_wb(self):
         def func_void(a):
             record.append(rffi.cast(lltype.Signed, a))
@@ -2422,7 +2377,7 @@
 
             ops = '''
             [i0, i1, i2, i3, i4, i5, i6, f0, f1]
-            cond_call(i1, ConstClass(func_ptr), %s)
+            cond_call_n(i1, 1, ConstClass(func_ptr), %s)
             guard_false(i0, descr=faildescr) [i1, i2, i3, i4, i5, i6, f0, f1]
             ''' % ', '.join(['i%d' % (j + 2) for j in range(i)] + 
["descr=calldescr"])
             loop = parse(ops, namespace={'faildescr': BasicFailDescr(),
@@ -2434,7 +2389,7 @@
             f2 = longlong.getfloatstorage(3.4)
             frame = self.cpu.execute_token(looptoken, 1, 0, 1, 2, 3, 4, 5, f1, 
f2)
             assert not called
-            for j in range(5):
+            for j in range(6):
                 assert self.cpu.get_int_value(frame, j) == j
             assert longlong.getrealfloat(self.cpu.get_float_value(frame, 6)) 
== 1.2
             assert longlong.getrealfloat(self.cpu.get_float_value(frame, 7)) 
== 3.4
@@ -2472,7 +2427,7 @@
             ops = '''
             [%s, %s, i3, i4]
             i2 = %s(%s)
-            cond_call(i2, ConstClass(func_ptr), i3, i4, descr=calldescr)
+            cond_call_n(i2, 1, ConstClass(func_ptr), i3, i4, descr=calldescr)
             guard_no_exception(descr=faildescr) []
             finish()
             ''' % ("i0" if operation.startswith('int') else "f0",
@@ -2492,6 +2447,51 @@
                                            67, 89)
             assert called == [(67, 89)]
 
+    def test_cond_call_value(self):
+        def func_int(*args):
+            called.append(args)
+            return len(args) * 100 + 1000
+
+        for i in range(5):
+            called = []
+
+            FUNC = self.FuncType([lltype.Signed] * i, lltype.Signed)
+            func_ptr = llhelper(lltype.Ptr(FUNC), func_int)
+            calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+                                             EffectInfo.MOST_GENERAL)
+
+            ops = '''
+            [i0, i1, i2, i3, i4, i5, i6, f0, f1]
+            i15 = cond_call_i(i1, 20, ConstClass(func_ptr), %s)
+            guard_false(i0, descr=faildescr) [i1,i2,i3,i4,i5,i6,i15, f0,f1]
+            finish(i15)
+            ''' % ', '.join(['i%d' % (j + 2) for j in range(i)] +
+                            ["descr=calldescr"])
+            loop = parse(ops, namespace={'faildescr': BasicFailDescr(),
+                                         'func_ptr': func_ptr,
+                                         'calldescr': calldescr})
+            looptoken = JitCellToken()
+            self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
+            f1 = longlong.getfloatstorage(1.2)
+            f2 = longlong.getfloatstorage(3.4)
+            frame = self.cpu.execute_token(looptoken, 1, 50, 1, 2, 3, 4, 5,
+                                           f1, f2)
+            assert not called
+            assert [self.cpu.get_int_value(frame, j) for j in range(7)] == [
+                        50, 1, 2, 3, 4, 5, 50]
+            assert longlong.getrealfloat(
+                        self.cpu.get_float_value(frame, 7)) == 1.2
+            assert longlong.getrealfloat(
+                        self.cpu.get_float_value(frame, 8)) == 3.4
+            #
+            frame = self.cpu.execute_token(looptoken, 1, 20, 1, 2, 3, 4, 5,
+                                           f1, f2)
+            assert called == [(1, 2, 3, 4)[:i]]
+            assert [self.cpu.get_int_value(frame, j) for j in range(7)] == [
+                        20, 1, 2, 3, 4, 5, i * 100 + 1000]
+            assert longlong.getrealfloat(self.cpu.get_float_value(frame, 7)) 
== 1.2
+            assert longlong.getrealfloat(self.cpu.get_float_value(frame, 8)) 
== 3.4
+
     def test_force_operations_returning_void(self):
         values = []
         def maybe_force(token, flag):
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
@@ -174,8 +174,8 @@
         # copy registers to the frame, with the exception of the
         # 'cond_call_register_arguments' and eax, because these have already
         # been saved by the caller.  Note that this is not symmetrical:
-        # these 5 registers are saved by the caller but restored here at
-        # the end of this function.
+        # these 5 registers are saved by the caller but 4 of them are
+        # restored here at the end of this function.
         self._push_all_regs_to_frame(mc, cond_call_register_arguments + [eax],
                                      supports_floats, callee_only)
         # the caller already did push_gcmap(store=True)
@@ -198,7 +198,7 @@
             mc.ADD(esp, imm(WORD * 7))
         self.set_extra_stack_depth(mc, 0)
         self.pop_gcmap(mc)   # cancel the push_gcmap(store=True) in the caller
-        self._pop_all_regs_from_frame(mc, [], supports_floats, callee_only)
+        self._pop_all_regs_from_frame(mc, [eax], supports_floats, callee_only)
         mc.RET()
         return mc.materialize(self.cpu, [])
 
@@ -1703,7 +1703,8 @@
         self.implement_guard(guard_token)
         # If the previous operation was a COND_CALL, overwrite its conditional
         # jump to jump over this GUARD_NO_EXCEPTION as well, if we can
-        if self._find_nearby_operation(-1).getopnum() == rop.COND_CALL:
+        if self._find_nearby_operation(-1).getopnum() in (
+                rop.COND_CALL_N, rop.COND_CALL_I, rop.COND_CALL_R):
             jmp_adr = self.previous_cond_call_jcond
             offset = self.mc.get_relative_pos() - jmp_adr
             if offset <= 127:
@@ -2381,7 +2382,7 @@
     def label(self):
         self._check_frame_depth_debug(self.mc)
 
-    def cond_call(self, op, gcmap, imm_func, arglocs):
+    def cond_call(self, op, gcmap, imm_func, arglocs, resloc=None):
         assert self.guard_success_cc >= 0
         self.mc.J_il8(rx86.invert_condition(self.guard_success_cc), 0)
                                                             # patched later
@@ -2394,11 +2395,14 @@
         # plus the register 'eax'
         base_ofs = self.cpu.get_baseofs_of_frame_field()
         should_be_saved = self._regalloc.rm.reg_bindings.values()
+        pop_eax = False
         for gpr in cond_call_register_arguments + [eax]:
-            if gpr not in should_be_saved:
+            if gpr not in should_be_saved or gpr is resloc:
                 continue
             v = gpr_reg_mgr_cls.all_reg_indexes[gpr.value]
             self.mc.MOV_br(v * WORD + base_ofs, gpr.value)
+            if gpr is eax:
+                pop_eax = True
         #
         # load the 0-to-4 arguments into these registers
         from rpython.jit.backend.x86.jump import remap_frame_layout
@@ -2422,8 +2426,15 @@
                 floats = True
         cond_call_adr = self.cond_call_slowpath[floats * 2 + callee_only]
         self.mc.CALL(imm(follow_jump(cond_call_adr)))
+        # if this is not a COND_CALL_N, we need to move the result in place
+        if resloc is not None and resloc is not eax:
+            self.mc.MOV(resloc, eax)
         # restoring the registers saved above, and doing pop_gcmap(), is left
-        # to the cond_call_slowpath helper.  We never have any result value.
+        # to the cond_call_slowpath helper.  We must only pop eax, if needed.
+        if pop_eax:
+            v = gpr_reg_mgr_cls.all_reg_indexes[eax.value]
+            self.mc.MOV_rb(eax.value, v * WORD + base_ofs)
+        #
         offset = self.mc.get_relative_pos() - jmp_adr
         assert 0 < offset <= 127
         self.mc.overwrite(jmp_adr-1, chr(offset))
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
@@ -928,7 +928,7 @@
 
     consider_cond_call_gc_wb_array = consider_cond_call_gc_wb
 
-    def XXXconsider_cond_call(self, op):
+    def consider_cond_call_n(self, op):
         # A 32-bit-only, asmgcc-only issue: 'cond_call_register_arguments'
         # contains edi and esi, which are also in asmgcroot.py:ASM_FRAMEDATA.
         # We must make sure that edi and esi do not contain GC pointers.
@@ -938,16 +938,27 @@
                     self.rm.force_spill_var(box)
                     assert box not in self.rm.reg_bindings
         #
-        assert op.type == 'v'
+        #assert op.type == 'v'
         args = op.getarglist()
-        assert 2 <= len(args) <= 4 + 2     # maximum 4 arguments
-        v = args[1]
-        assert isinstance(v, Const)
-        imm_func = self.rm.convert_to_imm(v)
-        arglocs = [self.loc(args[i]) for i in range(2, len(args))]
+        assert 3 <= len(args) <= 4 + 3     # maximum 4 arguments
+        v_func = args[2]
+        assert isinstance(v_func, Const)
+        imm_func = self.rm.convert_to_imm(v_func)
+        arglocs = [self.loc(args[i]) for i in range(3, len(args))]
         gcmap = self.get_gcmap()
-        self.load_condition_into_cc(op.getarg(0))
-        self.assembler.cond_call(op, gcmap, imm_func, arglocs)
+        if op.type == 'v':   # COND_CALL_N
+            self.load_condition_into_cc(op.getarg(0))
+            resloc = None
+        else:
+            condvalue_loc = self.loc(args[0])
+            assert not isinstance(condvalue_loc, ImmedLoc)
+            self.assembler.mc.CMP(condvalue_loc, self.loc(args[1]))
+            self.assembler.guard_success_cc = rx86.Conditions['E']
+            resloc = self.rm.force_result_in_reg(op, args[0])
+        self.assembler.cond_call(op, gcmap, imm_func, arglocs, resloc)
+
+    consider_cond_call_i = consider_cond_call_n
+    consider_cond_call_r = consider_cond_call_n
 
     def consider_call_malloc_nursery(self, op):
         size_box = op.getarg(0)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to