Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Include/internal/pycore_opcode_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 47 additions & 43 deletions Include/internal/pycore_uop_ids.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 44 additions & 28 deletions Include/internal/pycore_uop_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 60 additions & 0 deletions Lib/test/test_capi/test_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2349,6 +2349,66 @@ def testfunc(n):
assert ex is not None
"""))

def test_store_fast_pop_top_specialize_immortal(self):
def testfunc(n):
for _ in range(n):
x = None # _POP_TOP, as x's type is not yet known by optimizer.
x = None # _POP_TOP_NOP, as x = None

testfunc(TIER2_THRESHOLD)

ex = get_first_executor(testfunc)
self.assertIsNotNone(ex)
uops = get_opnames(ex)

self.assertIn("_POP_TOP_NOP", uops)

def test_store_fast_pop_top_specialize_int(self):
def testfunc(n):
y = int(1e6) # Big number so no int caching
for _ in range(n):
x = y + y # _POP_TOP, as x's type is not yet known by optimizer.
x = None # _POP_TOP_INT, as x = int

testfunc(TIER2_THRESHOLD)

ex = get_first_executor(testfunc)
self.assertIsNotNone(ex)
uops = get_opnames(ex)

self.assertIn("_POP_TOP_INT", uops)

def test_store_fast_pop_top_specialize_float(self):
def testfunc(n):
y = 1.0
for _ in range(n):
x = y + y # _POP_TOP, as x's type is not yet known by optimizer.
x = None # _POP_TOP_FLOAT, as x = int

testfunc(TIER2_THRESHOLD)

ex = get_first_executor(testfunc)
self.assertIsNotNone(ex)
uops = get_opnames(ex)

self.assertIn("_POP_TOP_FLOAT", uops)

def test_store_fast_pop_top_specialize_unicode(self):
def testfunc(n):
y = "hi"
for _ in range(n):
x = y + y # _POP_TOP, as x's type is not yet known by optimizer.
x = None # _POP_TOP_STR, as x = int

testfunc(TIER2_THRESHOLD)

ex = get_first_executor(testfunc)
self.assertIsNotNone(ex)
uops = get_opnames(ex)

self.assertIn("_POP_TOP_UNICODE", uops)



def global_identity(x):
return x
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Specialize ``POP_TOP`` and thus ``STORE_FAST`` in the JIT compiler by specializing for reference lifetime and type. This will also enable easier top of stack caching in the JIT compiler.
32 changes: 29 additions & 3 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,14 @@ dummy_func(
value = PyStackRef_FromPyObjectBorrow(obj);
}

replicate(8) inst(STORE_FAST, (value --)) {
_PyStackRef tmp = GETLOCAL(oparg);
replicate(8) op(_SWAP_FAST, (value -- trash)) {
trash = GETLOCAL(oparg);
GETLOCAL(oparg) = value;
DEAD(value);
PyStackRef_XCLOSE(tmp);
}

macro(STORE_FAST) = _SWAP_FAST + POP_TOP;

pseudo(STORE_FAST_MAYBE_NULL, (unused --)) = {
STORE_FAST,
};
Expand Down Expand Up @@ -344,6 +345,31 @@ dummy_func(
PyStackRef_XCLOSE(value);
}

op(_POP_TOP_NOP, (value --)) {
// TODO (gh-134584): Consider moving this to a function pointer table and replicate.
assert(!PyStackRef_RefcountOnObject(value) ||
_Py_IsImmortal((PyStackRef_AsPyObjectBorrow(value))));
DEAD(value);
}

op(_POP_TOP_INT, (value --)) {
// TODO (gh-134584): Consider moving this to a function pointer table and replicate.
assert(PyLong_CheckExact(PyStackRef_AsPyObjectBorrow(value)));
PyStackRef_CLOSE_SPECIALIZED(value, _PyLong_ExactDealloc);
}

op(_POP_TOP_FLOAT, (value --)) {
// TODO (gh-134584): Consider moving this to a function pointer table and replicate.
assert(PyFloat_CheckExact(PyStackRef_AsPyObjectBorrow(value)));
PyStackRef_CLOSE_SPECIALIZED(value, _PyFloat_ExactDealloc);
}

op(_POP_TOP_UNICODE, (value --)) {
// TODO (gh-134584): Consider moving this to a function pointer table and replicate.
assert(PyUnicode_CheckExact(PyStackRef_AsPyObjectBorrow(value)));
PyStackRef_CLOSE_SPECIALIZED(value, _PyUnicode_ExactDealloc);
}

tier2 op(_POP_TWO, (nos, tos --)) {
PyStackRef_CLOSE(tos);
PyStackRef_CLOSE(nos);
Expand Down
Loading
Loading