[pypy-commit] pypy default: Kill the resoperations GETFIELD_RAW_PURE and GETARRAYITEM_RAW_PURE. I

arigo noreply at buildbot.pypy.org
Sun Nov 8 03:52:42 EST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r80582:fbf3fccc271a
Date: 2015-11-08 09:35 +0100
http://bitbucket.org/pypy/pypy/changeset/fbf3fccc271a/

Log:	Kill the resoperations GETFIELD_RAW_PURE and GETARRAYITEM_RAW_PURE.
	I could not find a single case where PyPy emits them, and it
	simplifies code a little bit. Replaced with logic in pyjitpl to
	detect from the descr if the read can be constant-folded or not; if
	not, always emit the regular non-PURE operation. (It is common to
	have the jitcode do a getfield_raw on a vtable, but this case can
	always be constant-folded.)

	Fixes a theoretical segfault when the unroller would see a
	GET*_RAW_PURE and runs it speculatively in the 2nd unrolled version
	of the loop.

diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -680,8 +680,6 @@
     emit_op_getfield_gc_pure_f = _genop_getfield
     emit_op_getfield_raw_i = _genop_getfield
     emit_op_getfield_raw_f = _genop_getfield
-    emit_op_getfield_raw_pure_i = _genop_getfield
-    emit_op_getfield_raw_pure_f = _genop_getfield
 
     def emit_op_increment_debug_counter(self, op, arglocs, regalloc, fcond):
         base_loc, value_loc = arglocs
@@ -825,8 +823,6 @@
     emit_op_getarrayitem_gc_pure_f = _genop_getarrayitem
     emit_op_getarrayitem_raw_i = _genop_getarrayitem
     emit_op_getarrayitem_raw_f = _genop_getarrayitem
-    emit_op_getarrayitem_raw_pure_i = _genop_getarrayitem
-    emit_op_getarrayitem_raw_pure_f = _genop_getarrayitem
 
     def _load_from_mem(self, res_loc, base_loc, ofs_loc, scale,
                                             signed=False, fcond=c.AL):
diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -847,8 +847,6 @@
     prepare_op_getfield_gc_f = _prepare_op_getfield
     prepare_op_getfield_raw_i = _prepare_op_getfield
     prepare_op_getfield_raw_f = _prepare_op_getfield
-    prepare_op_getfield_raw_pure_i = _prepare_op_getfield
-    prepare_op_getfield_raw_pure_f = _prepare_op_getfield
     prepare_op_getfield_gc_pure_i = _prepare_op_getfield
     prepare_op_getfield_gc_pure_r = _prepare_op_getfield
     prepare_op_getfield_gc_pure_f = _prepare_op_getfield
@@ -942,8 +940,6 @@
     prepare_op_getarrayitem_gc_f = _prepare_op_getarrayitem
     prepare_op_getarrayitem_raw_i = _prepare_op_getarrayitem
     prepare_op_getarrayitem_raw_f = _prepare_op_getarrayitem
-    prepare_op_getarrayitem_raw_pure_i = _prepare_op_getarrayitem
-    prepare_op_getarrayitem_raw_pure_f = _prepare_op_getarrayitem
     prepare_op_getarrayitem_gc_pure_i = _prepare_op_getarrayitem
     prepare_op_getarrayitem_gc_pure_r = _prepare_op_getarrayitem
     prepare_op_getarrayitem_gc_pure_f = _prepare_op_getarrayitem
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
@@ -613,9 +613,6 @@
     bh_getfield_gc_f = bh_getfield_gc
 
     bh_getfield_raw = bh_getfield_gc
-    bh_getfield_raw_pure_i = bh_getfield_raw
-    bh_getfield_raw_pure_r = bh_getfield_raw
-    bh_getfield_raw_pure_f = bh_getfield_raw
     bh_getfield_raw_i = bh_getfield_raw
     bh_getfield_raw_r = bh_getfield_raw
     bh_getfield_raw_f = bh_getfield_raw
@@ -651,9 +648,6 @@
     bh_getarrayitem_gc_f = bh_getarrayitem_gc
 
     bh_getarrayitem_raw = bh_getarrayitem_gc
-    bh_getarrayitem_raw_pure_i = bh_getarrayitem_raw
-    bh_getarrayitem_raw_pure_r = bh_getarrayitem_raw
-    bh_getarrayitem_raw_pure_f = bh_getarrayitem_raw
     bh_getarrayitem_raw_i = bh_getarrayitem_raw
     bh_getarrayitem_raw_r = bh_getarrayitem_raw
     bh_getarrayitem_raw_f = bh_getarrayitem_raw
diff --git a/rpython/jit/backend/ppc/opassembler.py b/rpython/jit/backend/ppc/opassembler.py
--- a/rpython/jit/backend/ppc/opassembler.py
+++ b/rpython/jit/backend/ppc/opassembler.py
@@ -803,8 +803,6 @@
     emit_getfield_gc_pure_f = _genop_getfield
     emit_getfield_raw_i = _genop_getfield
     emit_getfield_raw_f = _genop_getfield
-    emit_getfield_raw_pure_i = _genop_getfield
-    emit_getfield_raw_pure_f = _genop_getfield
 
     SIZE2SCALE = dict([(1<<_i, _i) for _i in range(32)])
 
@@ -893,8 +891,6 @@
     emit_getarrayitem_gc_pure_f = _genop_getarray_or_interiorfield
     emit_getarrayitem_raw_i = _genop_getarray_or_interiorfield
     emit_getarrayitem_raw_f = _genop_getarray_or_interiorfield
-    emit_getarrayitem_raw_pure_i = _genop_getarray_or_interiorfield
-    emit_getarrayitem_raw_pure_f = _genop_getarray_or_interiorfield
 
     emit_raw_store = emit_setarrayitem_gc
     emit_raw_load_i = _genop_getarray_or_interiorfield
diff --git a/rpython/jit/backend/ppc/regalloc.py b/rpython/jit/backend/ppc/regalloc.py
--- a/rpython/jit/backend/ppc/regalloc.py
+++ b/rpython/jit/backend/ppc/regalloc.py
@@ -711,8 +711,6 @@
     prepare_getfield_gc_f = _prepare_getfield
     prepare_getfield_raw_i = _prepare_getfield
     prepare_getfield_raw_f = _prepare_getfield
-    prepare_getfield_raw_pure_i = _prepare_getfield
-    prepare_getfield_raw_pure_f = _prepare_getfield
     prepare_getfield_gc_pure_i = _prepare_getfield
     prepare_getfield_gc_pure_r = _prepare_getfield
     prepare_getfield_gc_pure_f = _prepare_getfield
@@ -796,8 +794,6 @@
     prepare_getarrayitem_gc_f = _prepare_getarrayitem
     prepare_getarrayitem_raw_i = _prepare_getarrayitem
     prepare_getarrayitem_raw_f = _prepare_getarrayitem
-    prepare_getarrayitem_raw_pure_i = _prepare_getarrayitem
-    prepare_getarrayitem_raw_pure_f = _prepare_getarrayitem
     prepare_getarrayitem_gc_pure_i = _prepare_getarrayitem
     prepare_getarrayitem_gc_pure_r = _prepare_getarrayitem
     prepare_getarrayitem_gc_pure_f = _prepare_getarrayitem
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
@@ -1477,8 +1477,6 @@
     genop_getfield_gc_f = _genop_getfield
     genop_getfield_raw_i = _genop_getfield
     genop_getfield_raw_f = _genop_getfield
-    genop_getfield_raw_pure_i = _genop_getfield
-    genop_getfield_raw_pure_f = _genop_getfield
     genop_getfield_gc_pure_i = _genop_getfield
     genop_getfield_gc_pure_r = _genop_getfield
     genop_getfield_gc_pure_f = _genop_getfield
@@ -1499,8 +1497,6 @@
     genop_getarrayitem_gc_pure_f = _genop_getarrayitem
     genop_getarrayitem_raw_i = _genop_getarrayitem
     genop_getarrayitem_raw_f = _genop_getarrayitem
-    genop_getarrayitem_raw_pure_i = _genop_getarrayitem
-    genop_getarrayitem_raw_pure_f = _genop_getarrayitem
 
     def _genop_raw_load(self, op, arglocs, resloc):
         base_loc, ofs_loc, size_loc, ofs, sign_loc = arglocs
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
@@ -1141,8 +1141,6 @@
     consider_getfield_gc_f = _consider_getfield
     consider_getfield_raw_i = _consider_getfield
     consider_getfield_raw_f = _consider_getfield
-    consider_getfield_raw_pure_i = _consider_getfield
-    consider_getfield_raw_pure_f = _consider_getfield
     consider_getfield_gc_pure_i = _consider_getfield
     consider_getfield_gc_pure_r = _consider_getfield
     consider_getfield_gc_pure_f = _consider_getfield
@@ -1172,8 +1170,6 @@
     consider_getarrayitem_gc_pure_i = _consider_getarrayitem
     consider_getarrayitem_gc_pure_r = _consider_getarrayitem
     consider_getarrayitem_gc_pure_f = _consider_getarrayitem
-    consider_getarrayitem_raw_pure_i = _consider_getarrayitem
-    consider_getarrayitem_raw_pure_f = _consider_getarrayitem
     consider_raw_load_i = _consider_getarrayitem
     consider_raw_load_f = _consider_getarrayitem
 
diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -703,6 +703,12 @@
             pure = '_pure'
         arraydescr = self.cpu.arraydescrof(ARRAY)
         kind = getkind(op.result.concretetype)
+        if ARRAY._gckind != 'gc':
+            assert ARRAY._gckind == 'raw'
+            if kind == 'r':
+                raise Exception("getarrayitem_raw_r not supported")
+            pure = ''   # always redetected from pyjitpl.py: we don't need
+                        # a '_pure' version of getarrayitem_raw
         return SpaceOperation('getarrayitem_%s_%s%s' % (ARRAY._gckind,
                                                         kind[0], pure),
                               [op.args[0], op.args[1], arraydescr],
@@ -792,12 +798,17 @@
         descr = self.cpu.fielddescrof(v_inst.concretetype.TO,
                                       c_fieldname.value)
         kind = getkind(RESULT)[0]
+        if argname != 'gc':
+            assert argname == 'raw'
+            if (kind, pure) == ('r', ''):
+                # note: a pure 'getfield_raw_r' is used e.g. to load class
+                # attributes that are GC objects, so that one is supported.
+                raise Exception("getfield_raw_r (without _pure) not supported")
+            pure = ''   # always redetected from pyjitpl.py: we don't need
+                        # a '_pure' version of getfield_raw
+        #
         op1 = SpaceOperation('getfield_%s_%s%s' % (argname, kind, pure),
                              [v_inst, descr], op.result)
-        if op1.opname == 'getfield_raw_r':
-            # note: 'getfield_raw_r_pure' is used e.g. to load class
-            # attributes that are GC objects, so that one is supported.
-            raise Exception("getfield_raw_r (without _pure) not supported")
         #
         if immut in (IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY):
             op1.opname += "_pure"
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
@@ -1266,9 +1266,6 @@
     def bhimpl_getarrayitem_raw_f(cpu, array, index, arraydescr):
         return cpu.bh_getarrayitem_raw_f(array, index, arraydescr)
 
-    bhimpl_getarrayitem_raw_i_pure = bhimpl_getarrayitem_raw_i
-    bhimpl_getarrayitem_raw_f_pure = bhimpl_getarrayitem_raw_f
-
     @arguments("cpu", "r", "i", "i", "d")
     def bhimpl_setarrayitem_gc_i(cpu, array, index, newvalue, arraydescr):
         cpu.bh_setarrayitem_gc_i(array, index, newvalue, arraydescr)
@@ -1387,17 +1384,12 @@
     def bhimpl_getfield_raw_i(cpu, struct, fielddescr):
         return cpu.bh_getfield_raw_i(struct, fielddescr)
     @arguments("cpu", "i", "d", returns="r")
-    def _bhimpl_getfield_raw_r(cpu, struct, fielddescr):
-        # only for 'getfield_raw_r_pure'
+    def bhimpl_getfield_raw_r(cpu, struct, fielddescr):   # for pure only
         return cpu.bh_getfield_raw_r(struct, fielddescr)
     @arguments("cpu", "i", "d", returns="f")
     def bhimpl_getfield_raw_f(cpu, struct, fielddescr):
         return cpu.bh_getfield_raw_f(struct, fielddescr)
 
-    bhimpl_getfield_raw_i_pure = bhimpl_getfield_raw_i
-    bhimpl_getfield_raw_r_pure = _bhimpl_getfield_raw_r
-    bhimpl_getfield_raw_f_pure = bhimpl_getfield_raw_f
-
     @arguments("cpu", "r", "i", "d")
     def bhimpl_setfield_gc_i(cpu, struct, newvalue, fielddescr):
         cpu.bh_setfield_gc_i(struct, newvalue, fielddescr)
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
@@ -500,16 +500,6 @@
                                        arraydescr, arraybox, indexbox)
 
     @arguments("box", "box", "descr")
-    def opimpl_getarrayitem_raw_i_pure(self, arraybox, indexbox, arraydescr):
-        return self.execute_with_descr(rop.GETARRAYITEM_RAW_PURE_I,
-                                       arraydescr, arraybox, indexbox)
-
-    @arguments("box", "box", "descr")
-    def opimpl_getarrayitem_raw_f_pure(self, arraybox, indexbox, arraydescr):
-        return self.execute_with_descr(rop.GETARRAYITEM_RAW_PURE_F,
-                                       arraydescr, arraybox, indexbox)
-
-    @arguments("box", "box", "descr")
     def opimpl_getarrayitem_gc_i_pure(self, arraybox, indexbox, arraydescr):
         if isinstance(arraybox, ConstPtr) and isinstance(indexbox, ConstInt):
             # if the arguments are directly constants, bypass the heapcache
@@ -792,19 +782,12 @@
     def opimpl_getfield_raw_i(self, box, fielddescr):
         return self.execute_with_descr(rop.GETFIELD_RAW_I, fielddescr, box)
     @arguments("box", "descr")
+    def opimpl_getfield_raw_r(self, box, fielddescr):   # for pure only
+        return self.execute_with_descr(rop.GETFIELD_RAW_R, fielddescr, box)
+    @arguments("box", "descr")
     def opimpl_getfield_raw_f(self, box, fielddescr):
         return self.execute_with_descr(rop.GETFIELD_RAW_F, fielddescr, box)
 
-    @arguments("box", "descr")
-    def opimpl_getfield_raw_i_pure(self, box, fielddescr):
-        return self.execute_with_descr(rop.GETFIELD_RAW_PURE_I, fielddescr, box)
-    @arguments("box", "descr")
-    def opimpl_getfield_raw_r_pure(self, box, fielddescr):
-        return self.execute_with_descr(rop.GETFIELD_RAW_PURE_R, fielddescr, box)
-    @arguments("box", "descr")
-    def opimpl_getfield_raw_f_pure(self, box, fielddescr):
-        return self.execute_with_descr(rop.GETFIELD_RAW_PURE_F, fielddescr, box)
-
     @arguments("box", "box", "descr")
     def _opimpl_setfield_raw_any(self, box, valuebox, fielddescr):
         self.execute_with_descr(rop.SETFIELD_RAW, fielddescr, box, valuebox)
@@ -2093,7 +2076,17 @@
         profiler = self.staticdata.profiler
         profiler.count_ops(opnum)
         resvalue = executor.execute(self.cpu, self, opnum, descr, *argboxes)
-        if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST:
+        #
+        is_pure = rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST
+        if not is_pure:
+            if (opnum == rop.GETFIELD_RAW_I or
+                opnum == rop.GETFIELD_RAW_R or
+                opnum == rop.GETFIELD_RAW_F or
+                opnum == rop.GETARRAYITEM_RAW_I or
+                opnum == rop.GETARRAYITEM_RAW_F):
+                is_pure = descr.is_always_pure()
+        #
+        if is_pure:
             return self._record_helper_pure(opnum, resvalue, descr, *argboxes)
         if rop._OVF_FIRST <= opnum <= rop._OVF_LAST:
             return self._record_helper_ovf(opnum, resvalue, descr, *argboxes)
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
@@ -1091,9 +1091,9 @@
     'STRLEN/1/i',
     'STRGETITEM/2/i',
     'GETFIELD_GC_PURE/1d/rfi',
-    'GETFIELD_RAW_PURE/1d/rfi',
     'GETARRAYITEM_GC_PURE/2d/rfi',
-    'GETARRAYITEM_RAW_PURE/2d/fi',
+    #'GETFIELD_RAW_PURE/1d/rfi',     these two operations not useful and
+    #'GETARRAYITEM_RAW_PURE/2d/fi',  dangerous when unrolling speculatively
     'UNICODELEN/1/i',
     'UNICODEGETITEM/2/i',
     #
@@ -1371,8 +1371,6 @@
     rop.GETARRAYITEM_GC_F: rop.VEC_GETARRAYITEM_GC_F,
     # note that there is no _PURE operation for vector operations.
     # reason: currently we do not care if it is pure or not!
-    rop.GETARRAYITEM_RAW_PURE_I: rop.VEC_GETARRAYITEM_RAW_I,
-    rop.GETARRAYITEM_RAW_PURE_F: rop.VEC_GETARRAYITEM_RAW_F,
     rop.GETARRAYITEM_GC_PURE_I: rop.VEC_GETARRAYITEM_GC_I,
     rop.GETARRAYITEM_GC_PURE_F: rop.VEC_GETARRAYITEM_GC_F,
     rop.RAW_STORE:        rop.VEC_RAW_STORE,
diff --git a/rpython/jit/metainterp/test/test_immutable.py b/rpython/jit/metainterp/test/test_immutable.py
--- a/rpython/jit/metainterp/test/test_immutable.py
+++ b/rpython/jit/metainterp/test/test_immutable.py
@@ -136,15 +136,15 @@
         #
         res = self.interp_operations(f, [0], disable_optimizations=True)
         assert res == 42
-        self.check_operations_history(getfield_raw_pure_i=1,
-                                      getarrayitem_raw_pure_i=1,
+        self.check_operations_history(getfield_raw_i=1,
+                                      getarrayitem_raw_i=1,
                                       int_mul=1)
         #
         # second try, in which we get num=0 constant-folded through f()
         res = self.interp_operations(f, [-1], disable_optimizations=True)
         assert res == 42
-        self.check_operations_history(getfield_raw_pure_i=0,
-                                      getarrayitem_raw_pure_i=0,
+        self.check_operations_history(getfield_raw_i=0,
+                                      getarrayitem_raw_i=0,
                                       int_mul=0)
 
     def test_read_on_promoted(self):


More information about the pypy-commit mailing list